如何在SAS中高效按指定时间点汇总各组事件发生数?
问题描述
需要生成如下格式的表格,汇总截至指定时间点的事件发生数量:
Timepoint GroupA GroupB le 30 n n le 90 n n le 180 n n le 365 n n
所用数据为包含group、tte和event(1表示发生事件)的时间事件数据,示例如下:
group tte event A 20 0 B 40 0 A 60 1 B 80 0 A 100 1 B 120 1
目前通过多次调用proc freq逐一生成结果,代码如下:
proc freq data = have; tables event * group/ nopercent nocol norow; where tte le 30 and event eq 1; run; proc freq data = have; tables event * group/ nopercent nocol norow; where tte le 60 and event eq 1; run;
请问是否有更高效的实现方式?
高效实现方案
方案1:PROC SQL一次性生成所有时间点汇总
通过union all合并多个时间点的统计结果,只需一次数据扫描即可完成所有时间点的累计事件数计算:
proc sql; create table event_summary as select 'le 30' as Timepoint, sum(case when group='A' and tte <=30 and event=1 then 1 else 0 end) as GroupA, sum(case when group='B' and tte <=30 and event=1 then 1 else 0 end) as GroupB from have union all select 'le 90' as Timepoint, sum(case when group='A' and tte <=90 and event=1 then 1 else 0 end) as GroupA, sum(case when group='B' and tte <=90 and event=1 then 1 else 0 end) as GroupB from have union all select 'le 180' as Timepoint, sum(case when group='A' and tte <=180 and event=1 then 1 else 0 end) as GroupA, sum(case when group='B' and tte <=180 and event=1 then 1 else 0 end) as GroupB from have union all select 'le 365' as Timepoint, sum(case when group='A' and tte <=365 and event=1 then 1 else 0 end) as GroupA, sum(case when group='B' and tte <=365 and event=1 then 1 else 0 end) as GroupB from have; quit; proc print data=event_summary noobs; run;
方案2:DATA步标记+PROC TABULATE汇总
先为每个观测标记是否符合各时间点的事件条件,再用制表过程快速生成结构化报表:
data have_flags; set have; /* 仅对发生事件的观测标记时间点符合情况,未发生事件的直接置0 */ if event = 1 then do; flag_30 = (tte <= 30); flag_90 = (tte <= 90); flag_180 = (tte <= 180); flag_365 = (tte <= 365); end; else do; flag_30 = 0; flag_90 = 0; flag_180 = 0; flag_365 = 0; end; run; proc tabulate data=have_flags format=8.0; class group; var flag_30 flag_90 flag_180 flag_365; table ('Timepoint' 'le 30' * flag_30.sum 'le 90' * flag_90.sum 'le 180' * flag_180.sum 'le 365' * flag_365.sum ), group=' ' * (GroupA='A' GroupB='B') / box='Timepoint'; run;
方案3:动态时间点处理(适合灵活调整时间点)
先创建时间点参数表,通过笛卡尔积关联原数据后批量统计,后续调整时间点只需修改参数表,无需改动统计代码:
/* 定义需要统计的时间点列表 */ data timepoints; length Timepoint $6; input Timepoint cutoff; datalines; le 30 30 le 90 90 le 180 180 le 365 365 ; run; /* 关联时间点与原数据,分组汇总累计事件数 */ proc sql; create table event_summary_dynamic as select t.Timepoint, sum(case when h.group='A' and h.tte <= t.cutoff and h.event=1 then 1 else 0 end) as GroupA, sum(case when h.group='B' and h.tte <= t.cutoff and h.event=1 then 1 else 0 end) as GroupB from timepoints t cross join have h group by t.Timepoint, t.cutoff order by t.cutoff; quit; proc print data=event_summary_dynamic noobs; run;
内容的提问来源于stack exchange,提问作者jackahall
相关产品推荐
相关产品推荐

