如何在SAS中对特定行范围进行动态排名及值统计?
在SAS中实现滑动窗口统计:计算最近5行中小于等于当前值的次数
要实现类似Excel =COUNTIF(C2:C6,"<="&C2) 的滑动窗口统计(对每一行,计算当前行及后续4行共5行中,值小于等于当前行值的次数),可以通过以下两种高效方法实现:
方法1:DATA步结合数组(推荐大数据集使用)
先按分组变量var_1和日期datevar降序排序,确保窗口对应“最近5条记录”;再用临时数组存储组内所有值,遍历窗口范围统计符合条件的数量:
/* 1. 按分组和日期降序排序 */ proc sort data=mydataset; by var_1 descending datevar; run; /* 2. 计算滑动窗口统计值 */ data want; set mydataset; by var_1; /* 定义临时数组存储组内的value,数组长度设为足够容纳每组最大观测数 */ array vals[100] _temporary_; retain vals: idx; /* 每组开始时重置数组和索引 */ if first.var_1 then do; call missing(of vals[*]); idx = 0; end; idx + 1; vals[idx] = value; /* 将当前行value存入数组 */ /* 统计当前行及后续4行(最多5行)中<=当前value的次数 */ rank_5_calc = 0; do j = idx to min(idx + 4, dim(vals)); if vals[j] <= value then rank_5_calc + 1; end; drop idx j; run;
方法2:PROC SQL自连接(逻辑直观)
先给每组内的观测编行号,再通过自连接匹配当前行及后续4行的记录,统计符合条件的数量:
/* 1. 按分组和日期降序排序,并添加组内行号 */ data mydataset_row; set mydataset; by var_1 descending datevar; if first.var_1 then row_num = 0; row_num + 1; run; /* 2. 自连接统计符合条件的记录数 */ proc sql; create table want as select a.*, sum(case when b.value <= a.value then 1 else 0 end) as rank_5_calc from mydataset_row a left join mydataset_row b on a.var_1 = b.var_1 and b.row_num between a.row_num and a.row_num + 4 group by a.var_1, a.row_num, a.datevar, a.value, a.rank_5; quit;
结果验证
两种方法计算出的rank_5_calc会和示例数据中的rank_5列完全匹配,比如第一行var_1=1、datevar=30DEC2020的value为-0.008855,后续4行的value均大于它,因此统计结果为1,和示例一致。
内容的提问来源于stack exchange,提问作者Tiago Vasconcelos
相关产品推荐
相关产品推荐

