SAS如何批量创建新观测使观测数匹配对应变量值
SAS展开非病例个体观测的实现方案
你原有DO循环无限运行的核心原因有两点:
by Popid语句写在循环内部,且逐行读取数据时,只有每个PopID的第一行汇总记录携带非缺失的N_noncases值,其余病例行的N_noncases为缺失值,缺失值和数值比较永远返回假,终止条件永远无法触发no_case计数器没有按PopID分组重置,跨人群计数会出现错乱
最简便稳定的实现方式是用带分组处理的DATA步,不需要额外生成中间表,一次运行即可得到目标结构数据集:
data want; set test; by PopID; /* 暂存每个组的非病例总数值,组首遇到汇总行时更新存储值 */ retain total_noncase .; if first.PopID then total_noncase = N_noncases; /* 先输出所有原始观测(含人群汇总行、所有病例行) */ output; /* 遍历到当前PopID组的最后一行时,生成对应数量的非病例观测 */ if last.PopID then do; CaseNum = .; N_cases = .; N_noncases = total_noncase; do No_case = 1 to total_noncase; output; end; end; drop total_noncase; run;
运行后输出的数据集完全匹配你给出的目标结构:
- 原始的人群汇总行、所有病例记录完整保留
- 每个PopID分组末尾自动新增对应数量的非病例记录,
No_case从1到组内非病例总数依次编号,非病例行的CaseNum、N_cases自动置空,N_noncases保留对应组的统计值
如果要使用PROC SQL实现,需要通过交叉连接生成辅助序列号,再和原始数据拼接,代码如下,适合小数据量场景使用:
proc sql noprint; /* 提取每个PopID的非病例总数 */ create table noncase_base as select distinct PopID, N_noncases from test where N_noncases is not null; /* 生成足够长度的连续序列号,交叉连接得到所有非病例观测 */ create table noncase_obs as select a.PopID, . as CaseNum, b.seq as No_case, . as N_cases, a.N_noncases from noncase_base a cross join ( select monotonic() as seq from sashelp.vmember where monotonic() <= (select max(N_noncases) from test) ) b where b.seq <= a.N_noncases; /* 拼接原始数据和非病例观测,按PopID排序 */ create table want as select PopID, CaseNum, . as No_case, N_cases, N_noncases from test outer union corr select * from noncase_obs order by PopID, CaseNum, No_case; quit;
后续拆分数据集做GEE分析时,直接筛选
CaseNum is not null or No_case is not null的记录即可得到个体水平分析集,自动排除每行PopID首条CaseNum和No_case均为空的人群汇总行,不需要额外做关联匹配。
内容的提问来源于stack exchange,提问作者sas_helpme
相关产品推荐
相关产品推荐

