基于SAS生成多月度标识:适配连续非零薪资区间需求
SAS滚动15个月周期的薪资标识生成方案
需求拆解
针对每个ID的滚动15个月窗口,完成以下逻辑:
- 筛选出窗口前3个月薪资全为0、后3个月薪资全为0的有效窗口
- 有效窗口的中间9个月中,仅将从第一个非零月起至第一个零月前的连续非零区间标记为1,其余月份(包括零月及后续非零月)标记为0
- 最终输出与原薪资变量一一对应的96个月度标识变量,不符合条件的月份统一标0
实现步骤与SAS代码
假设原始数据为宽表结构,每行对应一个ID,包含96个薪资变量(命名规则:salary_YYYYMM,如salary_201501至salary_202212)。以下代码通过「长表处理+滚动窗口判断+宽表输出」的流程实现需求:
1. 将宽表转换为长表
先把横向的薪资变量转为纵向的月度记录,方便滚动窗口计算:
/* 转换长表 */ data salary_long; set original_salary_data; length month $6.; array salary_arr[96] salary_201501-salary_202212; /* 替换为实际的薪资变量范围 */ array month_list[96] $6. _temporary_ ('201501','201502',...,'202212'); /* 按顺序生成96个月份字符串 */ do i=1 to 96; month = month_list[i]; salary = salary_arr[i]; output; end; drop i salary_201501-salary_202212; run; /* 按ID和月份排序 */ proc sort data=salary_long; by id month; run;
2. 滚动窗口判断与标识生成
在长表中,通过LAG和LEAD函数获取滚动15个月窗口内的薪资数据,判断有效窗口并生成标识:
data flag_long; set salary_long; by id; retain window_active; /* 定义滚动窗口的前后3个月、中间9个月薪资 */ lag1 = lag3(salary); /* 窗口第1个月薪资 */ lag2 = lag2(salary); /* 窗口第2个月薪资 */ lag3 = lag1(salary); /* 窗口第3个月薪资 */ lead1 = lead1(salary); /* 窗口第13个月薪资 */ lead2 = lead2(salary); /* 窗口第14个月薪资 */ lead3 = lead3(salary); /* 窗口第15个月薪资 */ /* 判断当前窗口是否为有效窗口(前3全0、后3全0) */ if first.id then window_active = 0; if (lag1=0 and lag2=0 and lag3=0 and lead1=0 and lead2=0 and lead3=0) then do; window_active = 1; /* 追踪中间9个月的连续非零区间 */ retain consecutive_nonzero; if first.id then consecutive_nonzero = 0; if salary > 0 and not missing(salary) then do; if consecutive_nonzero = 0 then consecutive_nonzero = 1; flag = 1; end; else do; consecutive_nonzero = 0; flag = 0; end; end; else do; /* 非有效窗口或已中断连续区间,标记为0 */ window_active = 0; consecutive_nonzero = 0; flag = 0; end; drop lag1-lag3 lead1-lead3; run;
3. 将长表转回宽表,生成96个月度标识变量
把处理后的长表转回宽表,得到与原薪资变量一一对应的标识变量:
proc transpose data=flag_long out=flag_wide(drop=_name_ _label_); by id; id month; var flag; run; /* 重命名标识变量为统一格式(如flag_YYYYMM) */ data final_flag_data; set flag_wide; rename _201501=flag_201501 _201502=flag_201502 ... _202212=flag_202212; /* 对应96个月份 */ run;
示例验证
针对题目中的两个示例:
- 周期薪资序列:
0,0,0,20,40,50,0,0,0,0,0,0,0,0,0- 有效窗口判断:前3月全0、后3月全0,符合条件
- 中间9个月连续非零区间为前3个月,对应标识:
0,0,0,1,1,1,0,0,0,0,0,0,0,0,0
- 周期薪资序列:
0,0,0,20,50,30,0,20,0,0,0,0,0,0,0- 有效窗口判断:前3月全0、后3月全0,符合条件
- 中间9个月中第4个月份为0,终止连续区间,对应标识:
0,0,0,1,1,1,0,0,0,0,0,0,0,0,0
以上代码可准确实现该逻辑,需注意根据实际数据的薪资变量命名、月份范围调整数组和重命名语句。
内容的提问来源于stack exchange,提问作者unluckyforsome
相关产品推荐
相关产品推荐

