如何为SAS数据集创建同ID6个月内手术史标识列?
问题说明
现有SAS数据集结构如下:
ID Visit_Date VISIT TYPE 001 JAN032000 OFFICE 001 DEC141999 SURGERY 001 FEB082002 OFFICE 002 JUN272000 OFFICE 002 APR142003 OFFICE 003 MAR292000 SURGERY 004 DEC072001 SURGERY 004 FEB142002 OFFICE
需求为新增列SX_6MO_B4_VISIT,规则:
- 门诊(OFFICE)记录:标记1/0,1表示该患者本次门诊前6个月内有手术(SURGERY)记录,0表示无
- 手术(SURGERY)记录:该列填充NA
用户尝试的PROC SQL代码报错“无法找到DATEDIFF函数”,代码如下:
PROC SQL; SELECT *, CASE WHEN EXISTS (SELECT 1 FROM DATA D2 WHERE D2.ID=D.ID AND D2.VISIT_TYPE= "SURGERY" AND AND D.VISIT_TYPE = "OFFICE" AND DATEDIFF(MM,D2.VISIT_DATE D.VISIT_DATE) <=6 ) THEN 1 ELSE 0 END AS SX_6MO_B4_VISIT FROM DATA D; QUIT;
错误原因
DATEDIFF是SQL Server等其他SQL方言的函数,SAS PROC SQL不支持该函数,需使用SAS原生日期函数替代- 代码存在语法错误:多了一个冗余的
AND,且DATEDIFF的参数缺少逗号分隔
解决方案
方法1:修正后的PROC SQL实现
先将字符型日期转换为SAS日期值,使用INTNX函数计算日期边界,再通过自连接判断手术记录是否存在:
PROC SQL; CREATE TABLE WANT AS SELECT ID, Visit_Date, `VISIT TYPE`, CASE WHEN `VISIT TYPE` = 'SURGERY' THEN . /* SAS数值型缺失值,后续可格式化为NA */ WHEN EXISTS ( SELECT 1 FROM DATA D2 WHERE D2.ID = D.ID AND D2.`VISIT TYPE` = 'SURGERY' /* 手术日期在当前门诊日期前6个月范围内 */ AND INPUT(D2.Visit_Date, DATE9.) >= INTNX('month', INPUT(D.Visit_Date, DATE9.), -6, 'same') AND INPUT(D2.Visit_Date, DATE9.) < INPUT(D.Visit_Date, DATE9.) ) THEN 1 ELSE 0 END AS SX_6MO_B4_VISIT FROM DATA D; QUIT; /* 可选:将缺失值格式化为显示NA */ PROC FORMAT; VALUE NA_FMT . = 'NA'; RUN; DATA WANT_DISPLAY; SET WANT; FORMAT SX_6MO_B4_VISIT NA_FMT.; RUN;
INPUT(Visit_Date, DATE9.):将字符型日期(如JAN032000)转换为SAS可识别的日期值INTNX('month', 日期, -6, 'same'):将当前门诊日期往前推6个月,保持日部分一致,得到时间范围的左边界- 手术日期需满足大于等于左边界且小于当前门诊日期,确保是门诊前6个月内的记录
方法2:DATA步实现(大数据集更高效)
通过排序+RETAIN保留最近手术日期,避免自连接,性能更优:
/* 按ID和日期升序排序 */ PROC SORT DATA=DATA OUT=SORTED_DATA; BY ID INPUT(Visit_Date, DATE9.); RUN; DATA WANT; SET SORTED_DATA; BY ID; RETAIN LAST_SX_DATE; /* 保留当前ID的最近手术日期 */ SAS_Visit_Date = INPUT(Visit_Date, DATE9.); /* 转换为SAS日期 */ /* 每个ID的第一条记录重置最近手术日期 */ IF FIRST.ID THEN LAST_SX_DATE = .; /* 更新最近手术日期 */ IF `VISIT TYPE` = 'SURGERY' THEN LAST_SX_DATE = SAS_Visit_Date; /* 生成目标列 */ IF `VISIT TYPE` = 'SURGERY' THEN SX_6MO_B4_VISIT = .; ELSE DO; IF NOT MISSING(LAST_SX_DATE) AND LAST_SX_DATE >= INTNX('month', SAS_Visit_Date, -6, 'same') AND LAST_SX_DATE < SAS_Visit_Date THEN SX_6MO_B4_VISIT = 1; ELSE SX_6MO_B4_VISIT = 0; END; DROP SAS_Visit_Date LAST_SX_DATE; /* 删除临时变量 */ RUN; /* 可选:格式化缺失值为NA */ PROC FORMAT; VALUE NA_FMT . = 'NA'; RUN; DATA WANT_DISPLAY; SET WANT; FORMAT SX_6MO_B4_VISIT NA_FMT.; RUN;
内容的提问来源于stack exchange,提问作者alex
相关产品推荐
相关产品推荐

