You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用数组简化SAS中Proc SQL多列重复聚合操作?

SAS用数组简化患者事件汇总代码

需求背景

现有SAS数据集morbidity,包含患者编号列Pat_TNO和20个以morb_开头的事件列(取值1=No,2=Yes),同一患者存在多行数据。需要生成新数据集,汇总每位患者是否至少发生过各类事件,替代原来需要手动写20个max()的Proc SQL代码。

解决方案:DATA步+数组实现

Proc SQL不支持数组操作,因此用DATA步结合BY分组+数组来自动处理所有morb_开头的列,无需逐个列名编写:

步骤1:按患者编号排序(BY分组要求数据集有序)

proc sort data=morbidity;
    by Pat_TNO;
run;

步骤2:用数组汇总事件状态

data morbidity_summary;
    set morbidity;
    by Pat_TNO;
    /* 定义数组,自动匹配所有以morb_开头的变量 */
    array morb_events[*] morb_:;
    /* 仅在患者第一行数据时初始化:默认所有事件为No(1) */
    if first.Pat_TNO then do;
        do i = 1 to dim(morb_events);
            morb_events[i] = 1;
        end;
    end;
    /* 遍历更新事件状态:只要某行事件为Yes(2),就保留为Yes */
    do i = 1 to dim(morb_events);
        if morb_events[i] = 2 then retain morb_events[i];
    end;
    /* 只输出患者最后一行,即汇总后的结果 */
    if last.Pat_TNO then output;
    /* 指定保留的变量 */
    keep Pat_TNO morb_:;
    /* 给所有morb_列应用YN.格式 */
    format morb_: yn.;
run;

代码说明

  • array morb_events[*] morb_::通过通配符morb_:自动捕获所有以morb_开头的列,不管列名是morb_amputation还是morb_mi都能匹配,无需手动列出20个列名
  • by Pat_TNO:按患者编号分组,first.Pat_TNO标记当前患者的第一行数据,last.Pat_TNO标记最后一行
  • retain语句:确保事件状态为Yes(2)时,后续行不会覆盖这个值,最终保留患者是否发生过该事件的结果
  • 最后只输出患者的最后一行,得到每位患者的汇总数据

另一种写法:用MAX函数直接取最大值

因为2(Yes)大于1(No),也可以用max()函数直接更新事件状态,逻辑更直观:

data morbidity_summary;
    set morbidity;
    by Pat_TNO;
    array morb_in[*] morb_:;
    array morb_out[*] morb_:;
    /* 保留输出变量的值 */
    retain morb_out:;
    /* 初始化患者首行数据 */
    if first.Pat_TNO then do;
        do i = 1 to dim(morb_out);
            morb_out[i] = 1;
        end;
    end;
    /* 逐行取最大值,只要出现过2就保留2 */
    do i = 1 to dim(morb_in);
        morb_out[i] = max(morb_out[i], morb_in[i]);
    end;
    if last.Pat_TNO then output;
    keep Pat_TNO morb_:;
    format morb_: yn.;
run;

内容的提问来源于stack exchange,提问作者jackahall

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 19:10:28