如何在SAS中从年终更改为年中

时间:2018-09-06 13:17:44

标签: arrays sas do-loops sas-studio

我目前在SAS工作,并以这种方式利用阵列:

Data Test;
input Payment2018-Payment2021;
datalines;

10 10 10 10
20 20 20 20
30 30 30 30
;
run;

我认为这会自动设置一个限制,无论是年初还是年底(如果我输入错了,请纠正我)

因此,如果我想说这是6月份的数据,并且付款将每9个月增加50%,我正在寻找一种方法让我的代码识别我的年份从6月底到下一年六月底

例如,如果我想说

Data Payment_Pct;
set test;

lastpayrise = "31Jul2018";

array payment:
array Pay_Inc(2018:2021) Pay_Inc: ;

Pay_Inc2018 = 0;
Pay_Inc2019 = 2; /*2 because there are two increments in 2019*/
Pay_Inc2020 = 1;
Pay_Inc2021 = 1;

do I = 2018 to 2021;

    if i = year(pay_inc) then payrise(i) * 50% * Pay_Inc(i);

end;

run;

对于一个条目手动执行此操作对我来说是一件好事,但对于我的uni项目,我需要算法自己解决这些问题,并且我目前正在阅读intck,但任何帮助将不胜感激!< / p>

P.s。拥有一个可以创建以下内容的算法会很棒

Pay_Inc2019 Pay_Inc2020 Pay_Inc2021
1           2           1

或者,很高兴知道SAS如何为2018:2021设置阵列,它是假设在年底还是可以将其设置为年中?或者

2 个答案:

答案 0 :(得分:1)

这是intnx()函数的一个很好的用例。在对齐日期方面,intnx()将是您最好的朋友。

在传统日历中,年份从01JAN开始。在您的日历中,年份从01JUN开始。这两个日期之间的差值恰好是6个月。我们想更改日期,以使年份从01JUN开始。这样您就可以将日期中的年份作为一部分,并确定新日历中的年份。

data want;
    format current_cal_year
           current_new_year year4.
    ;

    current_cal_year = intnx('year', '01JUN2018'd, 0, 'B');
    current_new_year = intnx('year.6', '01JUN2018'd, 1, 'B');
run;

请注意,我们将current_new_year移了一年。为了说明原因,让我们看看如果不将其转换一年会发生什么情况。

data want;
    format current_cal_year
           current_new_year year4.
    ;

    current_cal_year = intnx('year', '01JUN2018'd, 0, 'B');
    current_new_year = intnx('year.6', '01JUN2018'd, 0, 'B');
run;

current_new_year显示的是2018年,但我们确实在2019年。一年中的5个月,这个值是正确的。从6月到12月,年份值将不正确。通过将其偏移一年,我们将始终具有与此日期值关联的正确年份。用一年中的不同月份查看它,您会发现年份部分在整个时间中都保持正确。

data want;
    format cal_month date9.
           cal_year
           new_year year4.
    ;

    do i = 0 to 24;
        cal_month = intnx('month', '01JAN2016'd, i, 'B');
        cal_year = intnx('year', cal_month, i, 'B');
        new_year = intnx('year.6', cal_month, i+1, 'B');
        year_not_same = (year(cal_year) NE year(new_year) );
        output;
    end;

    drop i;
run;

答案 1 :(得分:1)

关于input Payment2018-Payment2021;,没有自动假定年份或日历。数字2018和2021是numbered range list

的界限
  

在带编号的范围列表中,只要您不违反用户提供的名称规则并且数字是连续的,则可以以任何数字开头和以任何数字结尾。

2018年至2021年数字的含义由程序员决定。您声明变量对应于编号年份中的6月付款。

您必须使用9个月的步骤来迭代日期,并根据该日期所属的年份增加一个计数器。

示例代码

动态地适应排列的变量名。

data _null_;

  array payments payment2018-payment2021;
  array Pay_Incs pay_inc2018-pay_inc2021; * must be same range numbers as payments;

  * obtain variable names of first and last element in the payments array;
  lower_varname = vname(payments(1));
  upper_varname = vname(payments(dim(payments)));

  * determine position of the range name numbers in those variable names;
  lower_year_position = prxmatch('/\d+\s*$/', lower_varname);
  upper_year_position = prxmatch('/\d+\s*$/', upper_varname);

  * extract range name numbers from the variable names;
  lower_year = input(substr(lower_varname,lower_year_position),12.);
  upper_year = input(substr(upper_varname,upper_year_position),12.);

  * prepare iteration of a date over the years that should be the name range numbers;
  date = mdy(06,01,lower_year); * june 1 of year corresponding to first variable in array;

  format date yymmdd10.;

  do _n_ = 1 by 1; * repurpose _n_ for an infinite do loop with interior leave;
    * increment by 9-months;
    date = intnx('month', date, 9);

    year = year(date);    
    if year > upper_year then leave;

    * increment counter for year in which iterating date falls within;
    Pay_Incs( year - lower_year + 1 ) + 1;
  end;

  put Pay_Incs(*)=;
run;

递增计数器注释

此声明中有很多要解压的地方

    Pay_Incs( year - lower_year + 1 ) + 1;
    语句末尾的
  • + 1将寻址数组元素增加1,并且是SUM Statement

    的语法
      

    变量+表达式

    sum语句等效于使用SUM函数和RETAIN语句,如下所示: retain variable 0; variable=sum(variable,expression);

  • year - lower_year + 1计算数组base-1索引1..N,该索引处理命名范围列表pay_inc<lower_year>-pay_inc<upper_year>

  • 中的相应变量
  • Pay_Incs( <computed index> )选择SUM语句的变量