0

我目前在 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 但任何帮助将不胜感激!

Ps 如果有一个算法可以创建以下内容,那就太好了

Pay_Inc2019 Pay_Inc2020 Pay_Inc2021
1           2           1

或者,很高兴知道 SAS 在为 2018:2021 设置数组时是如何工作的,它是假设年底还是您可以将其设置为年中还是?

4

2 回答 2

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;
于 2018-09-06T14:43:23.800 回答
1

关于input Payment2018-Payment2021;没有年份或日历的自动假设。数字 2018 和 2021 是编号范围列表的界限

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

数字 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语句的语法

    变量+表达式

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

  • year - lower_year + 1计算数组基数为 1 的索引 1..N,它寻址命名范围列表中的相应变量pay_inc<lower_year>-pay_inc<upper_year>

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

于 2018-09-06T14:43:54.757 回答