sas使用lag函数将代码扩展到多列并执行操作

sas使用lag函数将代码扩展到多列并执行操作,sas,Sas,我的数据集是这样的 bucket D_201009 D_201010 D_201011 D_201012 D_201101 D_201102 D_201103 0 0 0 0 0 0 0 0 1 1 0 0 0 1 0 0 2 3 0 3 0 1 6 3 3 0 0 0 0 0 0 0 4 0 4 0 0 0 0 0 5

我的数据集是这样的

bucket  D_201009    D_201010    D_201011    D_201012    D_201101    D_201102    D_201103
0   0   0   0   0   0   0   0
1   1   0   0   0   1   0   0
2   3   0   3   0   1   6   3
3   0   0   0   0   0   0   0
4   0   4   0   0   0   0   0
5   4   0   4   0   4   8   1
6   8   0   8   0   8   10  8
7   0   0   0   0   0   0   0
8   7   0   7   0   0   7   3
我想要的是这个

bucket  D_201009    D_201010    D_201011    D_201012    D_201101    D_201102    D_201103
0   23  4   22  0   14  31  15
1   23  4   22  0   14  31  15
2   22  4   22  0   13  31  15
3   19  4   19  0   12  25  12
4   19  4   19  0   12  25  12
5   19  0   19  0   12  25  12
6   15  0   15  0   8   17  11
7   7   0   7   0   0   7   3
8   7   0   7   0   0   7   3
其中,总和是存储单元0和1行的值,D_201009列对应的存储单元2=总和原始值(1),D_201009列对应的存储单元3的总和原始值(1)之前的值(滞后值)-3(原始值),并将该列标记为原始列名。我编写代码来执行一列

data test;
input bucket D_201009 D_201010 D_201011 D_201012 D_201101 D_201102 D_201103;
datalines;
0 0 0 0 0 0 0 0
1 1 0 0 0 1 0 0
2 3 0 3 0 1 6 3
3 0 0 0 0 0 0 0
4 0 4 0 0 0 0 0
5 4 0 4 0 4 8 1
6 8 0 8 0 8 10 8
7 0 0 0 0 0 0 0
8 7 0 7 0 0 7 3
;
run;
在宏中保存这些列名 仅查找一列的和 使用滞后来执行
数据结果(drop=D_201009 lag\u D_201009 rename=(sum=D_201009));
集合测试;
保留金额;
如果bucket<2,则sum=&total;
总和=总和(总和-滞后(D_201009));
跑

如何将代码更改为适用于列名存储为macro&orderedvars2的所有列

我的方法是将数据结构转换为更有用的数据结构;这样就不必使用宏变量。您可以改为通过处理来使用,并且没有延迟

我创建最终输出的方法是转置初始数据集,使每个bucket/D_变量有一行,然后按D_变量排序(_NAME_uuu包含这一点)。然后使用双道循环,首先计算和,然后减去值。注意,这里我不必使用Retain或Lag,我可以直接对值进行操作,因为我处于DoW循环中。我在减法之前输出,因为这似乎是你想要的。然后我重新移植回来

如果您有非常大的数据,这可能不是最快的选择,因为它需要经过几个步骤;如果你这样做了,你应该使用一个更有效的算法。但是,如果你不总是有相同的列,它可能是最不复杂的

proc transpose data=test out=test_t;
by bucket;
run;

proc sort data=test_t;
  by _name_ bucket;
run;

data want_t;
  do _n_ = 1 by 1 until (last._name_);
    set test_t;
    by _name_ bucket;
    sum_var = sum(sum_var,col1);
  end;
  do _n_ = 1 by 1 until (last._name_);
    set test_t;
    by _name_ bucket;
    output;
    sum_var = sum_var - col1;
  end;
run;

proc sort data=want_t;
by bucket _name_;
run;
proc transpose data=want_t out=want;
  by bucket;
  id _name_;
  var sum_var;
run;

使用proc summary获取每个变量的总和,然后定义多个数组

proc summary data=test;
var D:;
output out=sum(drop=_:) sum=/autoname;
run;

data want;
   set test;
   if _n_=1 then set sum;
   array var1 D_201009--D_201103;
   array var2 D_201009_sum--D_201103_sum;
   array var3 _D_201009 _D_201010 _D_201011 _D_201012 _D_201101 _D_201102 _D_201103;
   array temp (7) _temporary_;
   retain temp;
   do i=1 to dim(var1);
      lag=lag(var1(i));
      if bucket<2 then var3(i)=var2(i);
      else var3(i)=sum(temp(i),-lag);
      temp(i)=var3(i);
   end;
   drop D: lag i;
run;
proc汇总数据=测试;
变量D:;
output out=sum(drop=u:)sum=/autoname;
跑
数据需求;
集合测试;
如果_n_=1,则设置总和;
数组var1 D_201009--D_201103;
数组var2 D_201009_sum——D_201103_sum;
阵列var3\u D\u 201009\u D\u 201010\u D\u 201011\u D\u 201012\u D\u 201101\u D\u 201102\u D\u 201103;
阵列温度(7)\u临时\u;
保持温度;
i=1时变暗(var1);
滞后=滞后(var1(i));

如果bucket如果我理解正确,你想对列求和,然后从总数中减去每个观察值

获取总计很容易,只需使用
proc summary

然后将其与原始数据相结合。这是一种不用担心实际变量名的方法。在这个程序中,它将对所有以
d\u
开头的变量求和,但您可以使用任何您想要的变量列表。如果有100多个变量,请更改临时数组的维度

%let varlist=d_:;

* Get sums into variables with same names ;
proc summary data=have ;
  var &varlist ;
  output out=total sum=  ;
run;

data want ;
  set have(obs=0) /* Set variable order */
      total(keep=&varlist) /* Get totals */
      have(keep=&varlist)  /* Get lagged variables */
  ;
  array vars &varlist ;
  array total (100) _temporary_;
  set have (drop=&varlist);  /* Get non-lagged variables */
  do i=1 to dim(vars);
    if _n_>1 then vars(i)=total(i)-vars(i);
    total(i)=vars(i);
  end;
  drop i;
run;
如果缺少值,您可能希望在DO循环的开头添加这行代码:

vars(i)=coalesce(vars(i),0);
proc summary data=test;
var D:;
output out=sum(drop=_:) sum=/autoname;
run;

data want;
   set test;
   if _n_=1 then set sum;
   array var1 D_201009--D_201103;
   array var2 D_201009_sum--D_201103_sum;
   array var3 _D_201009 _D_201010 _D_201011 _D_201012 _D_201101 _D_201102 _D_201103;
   array temp (7) _temporary_;
   retain temp;
   do i=1 to dim(var1);
      lag=lag(var1(i));
      if bucket<2 then var3(i)=var2(i);
      else var3(i)=sum(temp(i),-lag);
      temp(i)=var3(i);
   end;
   drop D: lag i;
run;
%let varlist=d_:;

* Get sums into variables with same names ;
proc summary data=have ;
  var &varlist ;
  output out=total sum=  ;
run;

data want ;
  set have(obs=0) /* Set variable order */
      total(keep=&varlist) /* Get totals */
      have(keep=&varlist)  /* Get lagged variables */
  ;
  array vars &varlist ;
  array total (100) _temporary_;
  set have (drop=&varlist);  /* Get non-lagged variables */
  do i=1 to dim(vars);
    if _n_>1 then vars(i)=total(i)-vars(i);
    total(i)=vars(i);
  end;
  drop i;
run;
vars(i)=coalesce(vars(i),0);