代码之家  ›  专栏  ›  技术社区  ›  78282219

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

  •  0
  • 78282219  · 技术社区  · 7 年前

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

    Data Test;
    input Payment2018-Payment2021;
    datalines;
    
    10 10 10 10
    20 20 20 20
    30 30 30 30
    ;
    run;
    

    在我看来,这是自动假设的限制,无论是年初或年底(请纠正我,如果我错了)

    因此,如果我想说这是6月份的数据,并且付款将每9个月增加50%,那么我正在寻找一种方法,让我的代码认识到我的年份从6月底到下一个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,但任何帮助将不胜感激!

    顺便说一句,如果有一个算法可以创建以下

    Pay_Inc2019 Pay_Inc2020 Pay_Inc2021
    1           2           1
    

    或者,了解SAS如何为2018:2021设置阵列会很好,它是假设年底还是您可以将其设置为年中或?

    2 回复  |  直到 7 年前
        1
  •  1
  •   Richard    7 年前

    关于 input Payment2018-Payment2021; 没有人会自然而然地假设渴望或是挂历。2018年和2021年的数字是 numbered range list

    在编号范围列表中,只要不违反用户提供名称的规则,并且数字是连续的,就可以以任意数字开始,以任意数字结束。

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

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

    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 在语句的末尾,addressed array元素的增量为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

        2
  •  1
  •   Stu Sztukowski    7 年前

    这是 intnx() 功能。 会成为你最好的朋友。

    01JAN . 在你的日历里,一年从 01JUN . 这两个日期正好相差6个月。我们想改变日期,这样一年就可以开始了 6月1日 . 这将允许你把年份作为日期的一部分,并确定你在新日历中的年份。

    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;
    

    当前\新\年 显示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;
    
    推荐文章