按标签更新统计值:SAS中按ID拆分Hours并按Label=W分配的方法
SAS 实现按ID拆分总计到指定Label行
原始数据集
data have; input ID :$20. Label :$20. Hours :$20. Days :$20.; cards; 0001 w 3144 3 0001 w 23 54 0001 p 12 1 0002 m 456 34 0002 w 2 1 0002 s 231 45 0002 w 98 23 0003 w 12 6 0003 w 98 76 ; run;
需求说明
对每个ID执行以下操作:
- 计算该ID下所有
Hours的总和(总计) - 仅当
Label为"w"时,用该ID下所有Label="w"的Days总和作为分母,将总计按当前行的Days占比拆分到对应行 - 非"w"标签的行,
Hours设为缺失值
实现代码
/* 第一步:计算每个ID的Hours总计,以及该ID下Label='w'的Days总和 */ data summary; set have; by ID; retain total_hours total_w_days; /* 转换字符型变量为数值型,方便计算 */ hours_num = input(Hours, best20.); days_num = input(Days, best20.); if first.ID then do; total_hours = 0; total_w_days = 0; end; total_hours + hours_num; if Label = 'w' then total_w_days + days_num; if last.ID then output; keep ID total_hours total_w_days; run; /* 第二步:合并汇总数据到原始数据集,计算最终Hours值 */ data want; merge have summary; by ID; hours_num = input(Hours, best20.); days_num = input(Days, best20.); if Label = 'w' then do; /* 按Days占比拆分总计 */ final_hours = total_hours * days_num / total_w_days; end; else do; final_hours = .; end; /* 保留原始变量名,替换Hours值 */ Hours = put(final_hours, best10.6); drop hours_num days_num total_hours total_w_days final_hours; run; /* 查看输出结果 */ proc print data=want noobs; run;
代码逻辑说明
汇总计算阶段:
- 遍历每个ID,先把字符型的
Hours和Days转成数值型(原始数据定义为字符型,无法直接做算术运算) - 用
retain变量累计每个ID的Hours总和total_hours,以及该ID下所有Label="w"的Days总和total_w_days - 每个ID的最后一行输出汇总结果到
summary数据集
- 遍历每个ID,先把字符型的
合并计算阶段:
- 把原始数据集
have和汇总数据集summary按ID合并 - 对Label="w"的行,用
total_hours * 当前Days / total_w_days算出拆分后的Hours值 - 非"w"行直接把Hours设为缺失
- 最后把计算得到的数值型Hours转回字符型,保持原始变量的格式
- 把原始数据集
验证示例(ID=0001)
- 所有Hours总和:3144 + 23 + 12 = 3179
- Label="w"的Days总和:3 + 54 = 57
- 第一行w的Hours:3179 * 3 / 57 ≈ 167.3158
- 第二行w的Hours:3179 * 54 / 57 ≈ 3011.6842
- 第三行p的Hours设为缺失
内容的提问来源于stack exchange,提问作者NewUsr_stat
相关产品推荐
相关产品推荐

