使用SAS处理多列疾病标记:保留受试者3年内阳性诊断状态
问题描述
需要通过SAS按受试者处理,标记其过去3年内是否曾被诊断出对应疾病(disease1-disease3为二元是/否标记)。核心规则:一旦某受试者确诊过某疾病,后续年份的该疾病标记需保留为1。
原始数据集
| subject | year | disease1 | disease2 | disease3 |
|---|---|---|---|---|
| a | 2020 | 1 | 1 | 1 |
| a | 2021 | 0 | 0 | 0 |
| a | 2022 | 0 | 0 | 0 |
| b | 2020 | 0 | 1 | 0 |
| b | 2021 | 1 | 0 | 0 |
| b | 2022 | 0 | 0 | 1 |
期望输出数据集
| subject | year | disease1 | disease2 | disease3 |
|---|---|---|---|---|
| a | 2020 | 1 | 1 | 1 |
| a | 2021 | 1 | 1 | 1 |
| a | 2022 | 1 | 1 | 1 |
| b | 2020 | 0 | 1 | 0 |
| b | 2021 | 1 | 1 | 0 |
| b | 2022 | 1 | 1 | 1 |
尝试过do循环和retain语句,但因多列疾病变量处理陷入困境,寻求最优实现方法。
解决方案
针对多列疾病变量的批量处理,数组+RETAIN是最高效的实现方式,无需逐个变量编写逻辑。以下是两种可行方案:
方案1:DATA步+数组+RETAIN
利用数组批量遍历疾病变量,结合RETAIN保留历史阳性状态,代码扩展性强(新增疾病列只需修改数组范围):
data want; set have; by subject; /* 需确保数据集已按subject排序 */ array diseases[3] disease1-disease3; /* 定义数组包含所有疾病变量 */ array _history[3] _temporary_; /* 临时数组存储受试者疾病历史状态 */ /* 切换新受试者时,重置临时数组为0 */ if first.subject then do i = 1 to 3; _history[i] = 0; end; /* 更新历史状态:只要当前或历史为1,就保留为1 */ do i = 1 to 3; _history[i] = max(_history[i], diseases[i]); diseases[i] = _history[i]; /* 覆盖原变量为累计阳性状态 */ end; drop i; /* 清理临时变量 */ run;
代码说明
by subject:按受试者分组,first.subject识别新受试者的第一条记录,重置历史状态。- 临时数组
_history:仅在DATA步运行期间存在,存储每个受试者各疾病的累计阳性状态,不输出到最终数据集。 max(_history[i], diseases[i]):确保只要曾经确诊或当前确诊,状态就保持为1,完美匹配需求。
方案2:PROC SQL 分组累计
若偏好SQL语法,可通过分组窗口函数实现累计最大值,无需手动排序:
proc sql; create table want as select subject, year, max(disease1) over(partition by subject order by year rows between unbounded preceding and current row) as disease1, max(disease2) over(partition by subject order by year rows between unbounded preceding and current row) as disease2, max(disease3) over(partition by subject order by year rows between unbounded preceding and current row) as disease3 from have order by subject, year; quit;
代码说明
partition by subject:按受试者分组处理。order by year:确保按年份顺序累计状态。max(...) over(...):计算从分组第一条记录到当前行的最大值,即只要之前有过阳性记录,当前值就为1。
方案选择建议
- 若后续可能新增疾病列,优先选方案1,只需修改数组定义即可,无需调整核心逻辑。
- 若疾病变量较少且偏好SQL语法,方案2更简洁直观。
内容的提问来源于stack exchange,提问作者tatiwawa
相关产品推荐
相关产品推荐

