SAS编程|ADaM数据集构建中的关键函数应用

张开发
2026/5/31 1:37:08 15 分钟阅读
SAS编程|ADaM数据集构建中的关键函数应用
1. 条件判断函数ifc与ifn的实战应用在ADaM数据集构建过程中最常遇到的就是根据条件创建新变量。这时候ifc和ifn这对兄弟函数就是你的首选工具。ifc返回字符型结果ifn返回数值型结果它们的语法完全一致函数名(条件, 真值结果, 假值结果)。我处理临床试验数据时经常用它们来标记受试者状态。比如下面这个典型场景/* 将SDTM中的DSYN(是否完成研究)转换为ADaM中的ENRLFL(入组标志) */ data ADSL; set SDTM.DS; ENRLFL ifc(DSYN是, Y, N); run;这里有个实际踩过的坑原始数据中经常会出现缺失值。如果DSYN是缺失的ifc会默认返回空值。如果想显式处理缺失情况可以这样改进ENRLFL ifc(DSYN是, Y, ifc(DSYN否, N, U)); /* U代表未知 */数值型转换的场景也很常见。比如把问卷中的是/否转为1/0data ADQS; set SDTM.QS; QS1N ifn(QS1是, 1, 0); /* 数值型转换 */ QS2N ifn(QS2是, 100, ifn(QS2否, 50, .)); /* 支持嵌套 */ run;提示ifn处理数值型时如果条件结果本身就是数值可以直接用布尔表达式。比如ifn(BMI25, 1, 0)可以简写为(BMI25)2. 智能填充函数coalesce家族妙用处理临床数据时经常遇到同一个信息存储在多个变量的情况。coalescec(字符型)和coalesce(数值型)可以从左到右返回第一个非空值相当于SQL中的COALESCE。最近处理的一个实际案例受试者的种族信息可能记录在ETHNIC(标准值)或ETHNICO(其他描述)中data ADSL; set SDTM.DM; /* 优先取标准值若无则取其他描述 */ ETHNIC coalescec(ETHNIC, ETHNICO); run;日期处理是另一个典型场景。研究结束日期可能分布在多个字段EOSDT input(coalescec(DSEXDAT, DSENDAT, DSDTHDAT), yymmdd10.);数值型版本在处理实验室数据时特别有用。比如取多个时间点的最后一次检测值data ADLB; set SDTM.LB; /* 取最近一次检测的非缺失值 */ LBNRIND coalesce(LB4NRIND, LB3NRIND, LB2NRIND, LB1NRIND); run;3. 缺失值处理全攻略缺失值处理是ADaM构建的核心环节。SAS提供了一整套工具missing()判断是否缺失字符/数值通用n()统计非缺失数值个数nmiss()统计数值型缺失数cmiss()统计任意类型缺失数call missing()批量置空变量实际项目中最常用的是missing函数。比如处理随机分组数据data ADSL; set SDTM.DS; if missing(RANDNO) then do; ARM 筛选失败; ARMCD SCRNFAIL; end; run;实验室数据清洗时我经常用nmiss确保关键指标完整data ADLB; set SDTM.LB; if nmiss(LBSTRESN, LBNRIND) 0 then do; /* 只有数值和正常范围标志都完整时才计算Z分数 */ LBZSCORE (LBSTRESN - mean)/std; end; run;call missing在数据脱敏时特别有用data ADAE_ANON; set SDTM.AE; if USUBJID 001-001 then call missing(AESTDY, AEENDY); run;4. 字符串处理三剑客compress、scan、kindex原始数据清洗离不开字符串处理。compress函数远比想象中强大它不仅能删除空格还能按需保留/删除特定字符。最近处理的一个真实案例需要从50mg组中提取剂量数字data ADSL; set SDTM.DM; /* 只保留数字 */ DOSE compress(TRTGRP, , kd); run;scan和kindex组合使用可以解析复杂字符串。比如从50mg_试验组_A中提取信息data ADSL; set SDTM.DM; /* 提取第二部分 */ PHASE scan(ARM, 2, _); /* 判断是否含特定剂量 */ if kindex(ARM, 50mg) then DOSEGRP 1; run;处理中文数据时kscan比scan更可靠data ADCM; set SDTM.CM; /* 从阿司匹林_100mg_片剂中提取成分 */ CMP kscan(CMTRT, 1, _); run;5. 高级函数组合应用实战真正的数据处理高手都擅长函数组合。比如用catx构建唯一标识data ADAE; set SDTM.AE; /* 用-连接受试者ID和事件序号 */ AESPID catx(-, USUBJID, AESEQ); run;choosec和whichc配合可以实现编码转换data ADSL; set SDTM.DS; /* 数值转描述 */ SEXN whichc(SEX, 男, 女); /* 描述转数值 */ SEXC choosec(SEXN, M, F); run;日期时间处理时函数组合能解决很多难题data ADVS; set SDTM.VS; /* 合并日期时间并转为ISO格式 */ VSDTC catx(T, put(VSDAT, yymmdd10.), compress(VSTIM, :)); run;6. 性能优化技巧大数据量处理时函数使用方式直接影响性能compress的o选项在循环中使用时能提升50%性能/* 优化前 */ do i1 to 100000; x compress(y, 123); end; /* 优化后 */ do i1 to 100000; x compress(y, 123, o); end;避免嵌套ifc/ifn改用select when语句更清晰/* 不推荐 */ FLAG ifc(A1, X, ifc(B2, Y, Z)); /* 推荐 */ select; when(A1) FLAGX; when(B2) FLAGY; otherwise FLAGZ; end;批量处理缺失值call missing比单独赋值快3倍/* 慢 */ if x. then do; a.; b.; end; /* 快 */ if x. then call missing(a, b);7. CDISC合规性检查构建ADaM数据集必须符合CDISC标准函数能帮我们自动检查data ADSL; set SDTM.DM; /* 检查必填字段 */ MISSFL cmiss(USUBJID, SITEID, ARMCD); if MISSFL 0 then put WARNING: 缺失关键字段 USUBJID; /* 检查日期格式 */ if not missing(BRTHDTC) and length(BRTHDTC) ne 10 then put ERROR: 出生日期格式错误 USUBJID BRTHDTC; run;对于值域检查whichc特别有用data ADLB; set SDTM.LB; /* 检查是否在预定值域内 */ VALIDFL whichc(LBNRIND, NORMAL, HIGH, LOW) 0; run;8. 调试与错误处理复杂的数据转换难免出错这里分享几个调试技巧使用putlog查看中间结果data _null_; set SDTM.DM; TEST compress(USUBJID, 0); putlog DEBUG: USUBJID TEST; run;验证函数返回值data ADSL; set SDTM.DM; LEN lengthn(compress(ARM, 组)); if missing(LEN) then put WARNING: ARM处理异常 USUBJID ARM; run;构建检查数据集proc sql; create table CHECK_IFN as select distinct DSYN, ifc(DSYN是,Y,N) as CALC_FLAG from SDTM.DS where calculated CALC_FLAG not in (Y,N); quit;

更多文章