使用SAS PROC EXPAND计算三年滚动和结果异常,求原因与解决方法
问题分析与解决指导
问题描述
使用SAS计算每三年周期的滚动和时,结果出现了理论上不存在的极小数值(如类似-2.2737e-13的异常值),且滚动和应为0时该问题频发。即使尝试截断小数显示,问题仍未解决。
用到的代码
proc expand data=have out=want; by firmid ; convert vcinvest_annual=cum_vc/transformout=(movsum 3 trimleft 2); run;
data have; set have; put vcinvest_annual=6.4; run;
问题根源
- 浮点运算精度误差:SAS默认采用二进制浮点数存储数值,部分十进制小数(如0.1)无法被二进制精确表示,多次累加后会产生极小的误差值。当滚动和理论值为0时,这些误差会直接显现为非零的极小异常值。
- 数据排序缺失:如果
have数据集未按firmid分组后的时间变量排序,proc expand的movsum会计算错误的窗口,导致异常结果。 - 截断方式无效:
put vcinvest_annual=6.4;仅在输出时截断显示,并未修改变量实际存储的浮点值,滚动和计算仍会使用原始带误差的数值。
解决指导
步骤1:确保数据正确排序
先按firmid和时间变量(如year)排序,保证滚动窗口计算的正确性:proc sort data=have; by firmid year; run;步骤2:消除浮点误差
针对滚动和结果做精度修正,两种可选方法:- 在
proc expand中直接处理:proc expand data=have out=want; by firmid ; convert vcinvest_annual=cum_vc/transformout=(movsum 3 trimleft 2 round 1e-4); /* round 1e-4表示四舍五入到4位小数,可根据数据精度调整 */ run; - 在后续Data步中修正:
data want; set want; /* 四舍五入到4位小数 */ cum_vc = round(cum_vc, 1e-4); /* 或截断到4位小数:cum_vc = floor(cum_vc * 10000)/10000; */ /* 将极小误差值直接置为0 */ if abs(cum_vc) < 1e-6 then cum_vc = 0; run;
- 在
步骤3:检查原始数据精度
用完整格式查看原始变量的实际存储值,确认是否本身存在精度问题:data _null_; set have; put firmid= vcinvest_annual=best32.; run;如果原始数据就有精度误差,可先对
vcinvest_annual做四舍五入再计算滚动和。
内容的提问来源于stack exchange,提问作者Neal801
相关产品推荐
相关产品推荐

