如何在SAS中按类别计算含递推逻辑的4期移动平均值?
SAS按类别计算含递归的4周移动平均(测试期)
需求说明
- 按
category维度分组,区分训练期(week ≤ 5)和测试期(week > 5) - 训练期不计算移动平均值,测试期从第6周开始计算4周移动平均
- 测试期的移动平均值需递归纳入下一期的计算(即当期算出的均值作为下一期的输入值之一)
- 原数据中存在缺失的
value,计算时需忽略缺失值,按有效数据量计算均值
输入数据集
data have; input category week value ; datalines; a 1 10 a 2 5 a 3 a 4 30 a 5 50 b 1 30 b 2 5 b 3 b 4 0 b 5 50 ; run;
实现代码
data want; set have; by category; /* 保存最近4个有效数值的滚动变量,以及有效数据计数 */ retain val1 val2 val3 val4 count; moving_average = .; /* 每个类别开始时重置变量 */ if first.category then do; call missing(val1, val2, val3, val4); count = 0; end; /* 训练期:仅收集非缺失的value,不计算均值 */ if week <= 5 then do; if not missing(value) then do; val4 = val3; val3 = val2; val2 = val1; val1 = value; count = min(count + 1, 4); /* 最多保留4个有效数值 */ end; end; /* 测试期:计算递归移动平均 */ else do; moving_average = mean(of val1-val4); /* 将当期均值纳入下一期的滚动计算 */ val4 = val3; val3 = val2; val2 = val1; val1 = moving_average; count = min(count + 1, 4); end; output; /* 生成测试期后续周的记录(示例中每个类别生成4个测试周,可按需调整) */ if week = 5 then do; do week = 6 to (5 + 4); moving_average = mean(of val1-val4); val4 = val3; val3 = val2; val2 = val1; val1 = moving_average; count = min(count + 1, 4); value = .; output; end; end; drop val1 val2 val3 val4 count; run; /* 格式化移动平均值的小数位数,匹配示例显示 */ proc format; picture avgfmt low-high='00.000'; run; data want_formatted; set want; format moving_average avgfmt.; run;
代码逻辑解释
- 分组初始化:通过
by category和first.category触发变量重置,确保每个类别的计算独立,避免跨类别干扰。 - 训练期数据收集:仅保留非缺失的
value,滚动更新最近4个有效数值,最多存储4个值。 - 测试期递归计算:
- 从第6周开始,用最近保存的有效数值(含已计算的均值)计算当期移动平均
- 计算结果立即作为下一期的输入值,更新滚动变量
- 通过循环自动生成测试期后续周的记录,填充缺失的
value并计算均值
- 小数格式化:用自定义格式统一移动平均值的小数位数,与示例输出匹配。
结果验证
执行代码后,want_formatted数据集将生成与需求一致的结果:
- 类别b第6周均值:
(50+0+5)/3 = 18.333 - 类别b第7周均值:
(18.333+50+0)/3 = 22.777 - 类别b第8周均值:
(22.777+18.333+50+0)/4 = 22.775
内容的提问来源于stack exchange,提问作者Vicky sharma
相关产品推荐
相关产品推荐

