函数 LAG<n> 中的动态 n(变量)SAS_part2

Dynamic n in function LAG<n> (variable) SAS_part2

你知道如何在函数 LAGn(variable) 中使用 n 来引用程序中的另一个宏变量-> 在我的例子中是 max by V1?

   data example1;
input V1 value V2;
datalines;
a 1.0 2.0
a 1.0 1.0
a 1.0 1.0
b 1.0 1.0
b 1.0 1.0
;       

proc sql;
  select max(V2) format = 1. into :n
  from example1;
quit;

data example1;
  set example1;
  by V1;
  lagval=lag&n(V2);
  run;

来自 user667489 的代码,适用于一列。 现在n由V1改变。 我预计:

          MAX LAG
a 1.0 2.0  2  .
a 1.0 1.0  2  .
a 1.0 1.0  2  2
b 1.0 1.0  1  .
b 1.0 1.0  1  1
;    

LAG<n> 函数是一个固定深度的就地堆栈,特定于它的代码使用位置,因此特定于调用时的步进状态。堆栈很深,不能在运行时动态更改。

可以使用散列对象在 SAS DATA 步中实现动态滞后。双 DOW 技术允许测量一个组,然后对其进行操作。

示例代码

此示例使用定义了一个 hash 对象,该对象在一个组中维护一堆值。第一个 DOW 循环计算成为动态堆栈高度的字段的最大值。第二个 DOW 循环迭代组并检索滞后值,同时还为未来的项目滞后建立堆栈。

* some faux data;

data have (keep=group value duration);
  do group = 1 to 10;
    limit = ceil(4 * ranuni(6));
    put group= limit=;
    do _n_ = 1 to 8 + 10*ranuni(123);
      value = group*10 + _n_;
      duration = 1 + floor(limit*ranuni(123));
      output;
    end;
  end;
run;

* dynamic lag provided via hash;

data want;
  if _n_ = 1 then do;
    retain index lag_value .;
    declare hash lag_stack();
    lag_stack.defineKey('index');
    lag_stack.defineData('lag_value');
    lag_stack.defineDone();
  end;

  do _n_ = 1 by 1 until (last.group);
    set have;
    by group;
    max_duration = max(max_duration, duration);
  end;

  * max_duration within group is the lag lag_stack height;

  * pre-fill missings ;
  do index = 1-max_duration to 0;
    lag_stack.replace(key: index, data: .);
  end;

  do _n_ = 1 to _n_;
    set have;
    lag_stack.replace(key: _n_, data: value);
    lag_stack.find(key: _n_ - max_duration);
    output;
  end;

  drop index;
run;

另一种技术将涉及固定长度的环形数组而不是散列堆栈,但您需要在使用数组对 DATA 步进行编码之前计算所有组的最大滞后。

忘掉 LAG()。只需添加一个计数器变量并加入它即可。

让我们修正您的示例数据步骤,使其正常工作。

data example1;
  input V1 $ value V2;
datalines;
a 1 2
a 1 1
a 1 1
b 1 1
b 1 1
;

现在在每个 BY 组中添加一个唯一的行 ID。

data step1;
  set example1;
  by v1;
  if first.v1 then row=0;
  row+1;
run;

现在只需将此数据集与其自身连接起来即可。

proc sql ;
 create table want as
   select a.*,b.v2 as lag_v2
   from (select *,max(v2) as max_v2 from step1 group by v1) a
   left join step1 b
   on a.v1= b.v1 and a.row = b.row + a.max_v2
 ;
quit;

结果:

Obs    V1    value    V2    row    max_v2    lag_v2

 1     a       1       2     1        2         .
 2     a       1       1     2        2         .
 3     a       1       1     3        2         2
 4     b       1       1     1        1         .
 5     b       1       1     2        1         1

希望你的实际用例比这个例子更有意义。