SAS:在每行中以日期为条件对行进行求和

时间:2015-04-01 11:41:05

标签: sas

我在下表的前四列中显示了信息,并希望添加列 Calls_previous_3_days ,其中包含每个CustID对前三个日期的每个区域的调用总和。

即如果客户在2015年1月17日拨打支持电话,我希望新变量显示客户在2015年1月14日至2015年1月14日期间支持的电话总数。

如何计算 Calls_previous_3_days 列中的总和,具体取决于CustID,面积和日期?

CustID  Area     Date       Calls   Calls_previous_3_days
3137    Support  05Jan2015  1       0
3137    Support  14Jan2015  4       0 
3137    Support  16Jan2015  1       4
3137    Support  17Jan2015  1       5
3137    Support  20Jan2015  2       1
3137    Support  22Jan2015  1       2
5225    Support  26Jan2015  1       0
5225    Support  27Jan2015  1       1
5225    Support  28Jan2015  1       2
5225    Sales    14Feb2015  1       0       
5225    Sales    15Feb2015  1       1
5225    Sales    22Feb2015  1       0

2 个答案:

答案 0 :(得分:0)

您可以使用数组实现此目的,方法是存储最后三个值和日期,然后汇总日期满足条件的位置。

proc sort data = have;
    by CustID Area;;
run;
proc print;
data want;
    set have;
    by CustID Area;
    /* Create temporary array (which automatically retains) */
    array hist{3,2} _temporary_;
    /* Initialise the array values if starting a new group */
    if first.Area then call missing(of hist[*]);
    /* Sum the values in the array that satisfy your condition */
    callsp3 = sum(
        0,
        (sum(Date, - hist[1,2]) <= 3) * hist[1,1],
        (sum(Date, - hist[2,2]) <= 3) * hist[2,1],
        (sum(Date, - hist[3,2]) <= 3) * hist[3,1]
    );
    /* Store the current value/date in the array and shift old values down */
    hist[1,1] = hist[2,1];
    hist[1,2] = hist[2,2];
    hist[2,1] = hist[3,1];
    hist[2,2] = hist[3,2];
    hist[3,1] = Calls;
    hist[3,2] = Date;
run;

(通常使用SAS)有几种方法可以解决这个问题。您还可以调查lag() functions或使用proc sql自我加入数据,并使用on子句来指定您的条件。我更喜欢数组方法,因为lag()有一些gotchas,自连接会慢一些。但是,如果您可能需要不同或更长的窗口,那么由于代码的长度,阵列方法可能会变得有些笨拙。如果您对宏语言有信心,可以减轻这种情况,但调查其他方法可能会更好。


如果您获得SAS / ETS许可,您应该可以使用proc expand实现此目标。我不能确认这完全是你想要的,因为我没有许可证。

proc expand data = have out = want from = day to = day;
    by CustID Area;
    id Date;
    convert calls = callsp3 / method = none transformout = (movsum 4);
run;
data want; 
    set want (where = (calls ~= .));
    callsp3 = callsp3 - calls;
run;

答案 1 :(得分:0)

LAG功能,正如@SRSwift详细说明,当然效果很好。

此外,这是一个SQL解决方案。使用数据步骤将0替换为缺失,不确定SQL步骤中的CASE语句是否是最佳方法。

Data HAVE;
Input custid $ area $ date:date9. calls;
format date date9.;
datalines;
3137    Support  05Jan2015  1
3137    Support  14Jan2015  4
3137    Support  16Jan2015  1
3137    Support  17Jan2015  1
3137    Support  20Jan2015  2
3137    Support  22Jan2015  1
5225    Support  26Jan2015  1
5225    Support  27Jan2015  1
5225    Support  28Jan2015  1
5225    Sales    14Feb2015  1
5225    Sales    15Feb2015  1
5225    Sales    22Feb2015  1
;
Run;

Proc sql;
Create table WANT as
Select custid,area,date,calls,
(select sum(calls) from have b where a.custid=b.custid and 
  a.area=a.area and (a.date-3<=b.date<a.date)) as Calls_Previous_3_Days
From HAVE a;
Quit;

Data WANT;
Set WANT;
If missing(calls_previous_3_days) then Calls_Previous_3_Days=0;
Run;