如何在SAS中比较不同列交叉值并按规则生成False_Flag列
SAS实现方案
1. 前置处理
1.1 日期格式转换(若为字符型)
如果你的DATE1、DATE2是字符类型,需要先转换为SAS数值型日期,后续才能正确比较大小:
/* 转换日期格式,原数据集名为have */ data have_fix; set have; /* 按date9.格式解析字符日期,生成数值型日期 */ DATE1_num = input(DATE1, date9.); DATE2_num = input(DATE2, date9.); /* 保留原显示格式 */ format DATE1_num DATE2_num date9.; /* 替换原字段名 */ rename DATE1_num=DATE1 DATE2_num=DATE2; drop DATE1 DATE2; run;
1.2 排序
按ID和DATE1升序排序,保证同ID下的行按时间先后排列:
proc sort data=have_fix out=have_sorted; by ID DATE1; run;
2. 生成FALSE_FLAG字段
2.1 常规方案(SAS 9.4M5及以上版本,支持LEAD函数)
data want; set have_sorted; by ID; /* 读取前一行的ID、FLAG、DATE2 */ lag_ID = lag(ID); lag_FLAG = lag(FLAG); lag_DATE2 = lag(DATE2); /* 读取后一行的ID、FLAG、DATE1 */ lead_ID = lead(ID); lead_FLAG = lead(FLAG); lead_DATE1 = lead(DATE1); FALSE_FLAG = 0; /* 默认赋值0 */ /* 当前行是R,后一行是同ID的D,且当前行DATE2等于后一行DATE1,当前行标1 */ if not last.ID and FLAG='R' and lead_FLAG='D' and DATE2=lead_DATE1 then FALSE_FLAG=1; /* 当前行是D,前一行是同ID的R,且前一行DATE2等于当前行DATE1,当前行标1 */ if not first.ID and FLAG='D' and lag_FLAG='R' and lag_DATE2=DATE1 then FALSE_FLAG=1; /* 删除临时辅助变量,不输出到结果表 */ drop lag_: lead_:; run;
2.2 低版本SAS兼容方案(无LEAD函数)
如果你的SAS版本不支持内置LEAD函数,可以用哈希表实现后一行值的读取:
data want; if _n_=1 then do; /* 把所有行的ID、DATE1、FLAG存入哈希表,按行号索引 */ declare hash h(dataset:'have_sorted(keep=ID DATE1 FLAG rename=(ID=lead_ID DATE1=lead_DATE1 FLAG=lead_FLAG))'); h.definekey('rownum'); h.definedata('lead_ID','lead_DATE1','lead_FLAG'); h.definedone(); do rownum=1 to nobs; set have_sorted point=rownum nobs=nobs; h.replace(); end; end; set have_sorted; rownum = _n_; lag_ID = lag(ID); lag_FLAG = lag(FLAG); lag_DATE2 = lag(DATE2); /* 读取后一行值,最后一行没有后行,赋值为空 */ lead_ID=.; lead_DATE1=.; lead_FLAG=' '; if rownum < nobs then h.find(key:rownum+1); FALSE_FLAG = 0; if not last.ID and FLAG='R' and lead_FLAG='D' and DATE2=lead_DATE1 then FALSE_FLAG=1; if not first.ID and FLAG='D' and lag_FLAG='R' and lag_DATE2=DATE1 then FALSE_FLAG=1; drop rownum lag_: lead_:; run;
内容的提问来源于stack exchange,提问作者merts97
相关产品推荐
相关产品推荐

