我坚持要在SAS中解决此问题。可能不是那么复杂,但是我尝试了使用“保留”和“执行”循环的方法,这些方法都行不通。
基本上每个ID在每个日期都有数据。基于其他变量,它们可以进入减少状态(变量步长> 0),有时它们将满足最终条件1。如果满足condition1 = 1,则需要从减少开始就标记“情节”。
下面是我的数据的示例,我需要列标志。我将数据按升序排列以便我们理解
ID date step condition1 flag
z 1 0 .
z 2 0 .
z 3 0 .
z 4 1 . TRUE
z 5 2 . TRUE
z 6 2 . TRUE
z 7 3 . TRUE
z 8 4 . TRUE
z 10 4 . TRUE
z 11 4 1 TRUE
z 12 4 .
z 13 4 .
z 14 0 .
z 15 0 .
z 16 0 .
z 17 1 .
z 18 2 .
z 19 2 .
z 20 0 .
z 21 0 .
编辑:带有用于确定减少量的变量的表
ID date quantity step condition1 flag
z 1 90 0 .
z 2 90 0 .
z 3 100 0 .
z 4 90 1 . TRUE
z 5 80 2 . TRUE
z 6 80 2 . TRUE
z 7 50 3 . TRUE
z 8 0 4 . TRUE
z 10 0 4 . TRUE
z 11 0 4 1 TRUE
z 12 0 4 .
z 13 0 4 .
z 14 40 0 .
z 15 50 0 .
z 16 60 0 .
z 17 40 1 .
z 18 40 2 .
z 19 30 2 .
z 20 60 0 .
z 21 60 0 .
我试图按ID和降序对它进行排序,这似乎很有意义。
proc sort data= have;
by id descending date ;
run;
这是我尝试过的许多方法之一-但它卡住了; (已编辑)
DATA want ;
SET have;
if four=1 then do;
do until (step<1) ; flag=1; output;
end;
end;
run;
任何帮助表示赞赏。我可能只需要正确方向的提示。谢谢
答案 0 :(得分:1)
您不能在数据步骤中像这样使用do until
-它会进行迭代,但不会从输入数据集中读取任何其他观察值。
我认为您需要的主要想法是维护单独的状态变量以记住您已经看到的内容:
proc sort data=have;
by id date;
run;
data want;
retain episode_started episode_finished;
set have;
by id;
if first.id then do;
episode_started = 0;
episode_finished = 0;
end;
if step > 0 then episode_started = 1;
if episode_started and not episode_finished then flag = 'TRUE';
output;
if condition1 then episode_finished = 1;
run;
我还没有测试过,但是应该很接近。您可以查看输出数据集中添加的两个标志,以了解何时以及如何对其进行设置。您可以通过使用具有两个以上值的单个状态变量来实现相同的目的,但是我认为上面的代码更加清晰。
答案 1 :(得分:1)
在需要对一组行进行评估的组内处理(必须应用于同一行)可以使用“串行DOW”编码模式来完成。您的数据可能在一个组中有多个细分,因此整个内容将嵌套在一个外部do循环中。
示例
您的步骤和条件组合约束没有得到充分说明,因此示例逻辑可能不会涵盖所有情况。
在此示例中,index_first_after_last_zero
使用step > 0
跟踪行的开始,并以condition1 = 1
结束行
data want;
do until (last.id);
segment = sum(segment,1); * <------ helper for understanding logic;
* 'measuring loop' that computes or tracks some multi-row condition within group;
do index = 1 by 1 until (condition1 or last.id);
set have; * <------ SET inside loop;
by id date; * <------ BY for last.id and ensures dates are ordered;
* track start of last run of non-zero steps;
if step=0 then
index_first_after_last_zero = index + 1;
end;
* track end of run flag;
segment_end_condition = condition1;
* end of loop value is fixed at start of loop and thus not affected by automatic BY 1 increment;
* thus 1 to index iterates same number of rows as the 'measuring' loop;
do index = 1 to index;
set have; * <------ second SET use a separate file buffer than first SET;
* apply flag value -- missing for pre-run rows, and end of run flag to run rows;
if index < index_first_after_last_zero
then flag = .;
else flag = segment_end_condition;
OUTPUT;
end;
end;
run;