Table
Table优化:减少冗余计算
原代码在if块内反复调用index()——每条记录重复10+次。改为前置计算布尔值:
SAS
/* ❌ 低效:if块内重复index() */
if TRTEMFL = "Y" then do;
ACNFL1 = ifc(index(AEACN1,"暂停用药")>0 or index(AEACN2,"暂停用药")>0, "Y", "N");
ACNFL2 = ifc(index(AEACN1,"暂停用药")>0 and index(AEACN2,"暂停用药")>0, "Y", "N");
/* ... 重复8次index() ... */
end;
/* ✅ 高效:前置计算布尔值,后面直接引用 */
ACN_PAUSE1 = index(AEACN1, "暂停用药") > 0; /* 只算一次 */
ACN_PAUSE2 = index(AEACN2, "暂停用药") > 0;
ACN_STOP1 = index(AEACN1, "永久停药") > 0;
ACN_STOP2 = index(AEACN2, "永久停药") > 0;
if TRTEMFL = "Y" then do;
ACNFL1 = ifc(ACN_PAUSE1 | ACN_PAUSE2, "Y", "N"); /* 直接引用 */
ACNFL2 = ifc(ACN_PAUSE1 & ACN_PAUSE2, "Y", "N");
/* ... */
end;
drop ACN_PAUSE1 ACN_PAUSE2 ACN_STOP1 ACN_STOP2;
手动构建dummy数据
有些Table需要0行也显示——当某SOC/PT下没有事件时,构建空的dummy记录来占位。
SAS
/* TEAE Table dummy:每个SOC/PT都遍历所有治疗组和relord */
data DUMMY;
set DUM;
if AESOC = "" then do; /* "Any TEAEs" 行 */
GRP=1; ORD1=0;
do TRT=1 to 11,99; output; end;
GRP=1; ORD1=1;
do RELORD=1 to 2;
do TRT=1 to 11,99; output; end;
end;
end;
/* SOC和PT级别同理... */
run;
Listing
Hash对象维护排序序号
Listing中需要按col1、col2分组内对col3的值从1开始编号——Hash对象比DATA步retain更可靠。
SAS
/* Hash对象:按(col1, col2)内col3首次出现序号递增 */
data FIN1;
if _n_ = 1 then do;
dcl hash H();
H.defineKey('COL1', 'COL2', 'COL3');
H.defineData('SEQ');
H.defineDone();
end;
set FIN;
by ORD COL1 COL2 VISITNUM COL3;
retain MAXSEQ 0;
if first.COL2 then MAXSEQ = 0;
if H.check() ^= 0 then do;
MAXSEQ + 1;
SEQ = MAXSEQ;
RC = H.add();
end;
else RC = H.find();
drop RC MAXSEQ;
run;
proc sort; by ORD COL1 COL2 SEQ COL3 VISITNUM; run;
分页 & 受试者不跨页
SAS
/* 每10条记录一页 */
PAGE = ceil(_n_ / 10);
/* 波浪号转义:避免RTF解析为不可见字符 */
if index(VISIT, '~') then
VISIT = tranwrd(VISIT, '~', '~{unicode 007E}');
ODS导出Excel
SAS
/* ODS Excel 导出(推荐:比PROC EXPORT更可控) */
ods excel file="&OUTPATH.\ADaM_&RUNDATE._rawdata.xlsx"
options(
frozen_headers = '1'
autofilter = 'all'
embedded_titles= 'yes'
);
proc print data=ADAM.ADAE label noobs; run;
proc print data=ADAM.ADCM label noobs; run;
ods excel close;
常见坑
⚠️ raw_text排序异常?先看format。出Table时如果排序结果和预期不符,检查format是否截断了实际值。
⚠️ SAS中一个中文占3字节。UTF-8编码下定义变量length时中文×3,否则截断。
⚠️ cats会自动去掉两端空格,catx会默认中间加一个空格。两个函数的行为差异常在拼接Table列时造成格式问题。
⚠️ ODS Excel vs PROC EXPORT:ODS Excel支持frozen_headers/autofilter等;PROC EXPORT轻量但格式控制弱。交付推荐ODS。