使用SAS LAG函数按_ric分组取close_midpoint滞后值的代码问题
问题根源:SAS
lag()函数的特殊工作机制 咱们先拆解下你遇到的问题——这其实是对SAS lag()函数的常见误解:它不是直接取“上一条观测的值”,而是按函数的执行次数来维护缓存队列。只有当lag()函数被执行时,SAS才会把当前变量值放进队列,同时返回队列里最旧的那个值;如果函数没被执行,队列就不会更新。
回到你的代码:
data test; set HAVE; lric=lag(_ric); if lric=_ric then lclose_midpoint=lag(close_midpoint); else lclose_midpoint=.; run;
当切换到新的_ric组时(比如第7条观测是新组的第一条),lric ne _ric,这时你没有执行lag(close_midpoint),所以这个函数的缓存队列里还留着上一组最后一次执行时的4.2。等到新组的第二条观测(此时lric=_ric)执行lag(close_midpoint),返回的就是缓存里的旧值,而不是新组第一条的4.675。
两种靠谱的解决方法
不管用哪种方法,第一步必须先按_ric+时间变量排序,SAS是按数据集里的观测顺序处理的,不排序的话组内观测乱序,滞后值肯定错。
方法一:用BY组处理(推荐,简洁不易错)
SAS的BY组会自动识别每个组的起始/结束,我们可以利用first._ric来重置滞后值:
/* 先按组+时间排序,确保观测顺序正确 */ proc sort data=HAVE; by _ric time_col; /* 把time_col换成你的实际时间变量,比如date */ run; data test; set HAVE; by _ric; /* 组内第一条观测,滞后值设为缺失 */ if first._ric then lclose_midpoint = .; /* 非第一条,取本组前一个观测的close_midpoint */ else lclose_midpoint = lag(close_midpoint); run;
如果想要完全避开lag()的缓存问题,也可以用retain手动维护前值,稳定性更高:
proc sort data=HAVE; by _ric time_col; run; data test; set HAVE; by _ric; retain prev_close; /* 保留上一条的close_midpoint值 */ if first._ric then do; lclose_midpoint = .; prev_close = close_midpoint; end; else do; lclose_midpoint = prev_close; prev_close = close_midpoint; end; run;
方法二:手动维护分组的滞后值(不用BY组的场景)
如果不想用BY组,也可以用retain同时跟踪上一个组和上一个值:
proc sort data=HAVE; by _ric time_col; run; data test; set HAVE; retain prev_ric prev_close; /* 保留上一条的组和值 */ /* 判断是否是新组 */ if _ric ne prev_ric then do; lclose_midpoint = .; prev_ric = _ric; /* 更新当前组 */ end; else do; lclose_midpoint = prev_close; /* 取本组前一个值 */ end; prev_close = close_midpoint; /* 更新前值为当前值,供下一条用 */ run;
关键提醒
一定要确认你的数据集已经按_ric和时间变量排序,否则哪怕代码写对了,观测顺序乱的话,滞后值还是会出错。
内容的提问来源于stack exchange,提问作者Neal801
相关产品推荐
相关产品推荐

