这里有什么?
从ADAE、ADCM、ADPC中提炼的反复出现的编程模式。不是列出所有变量怎么算——而是"这种数据结构怎么处理"的通用解法。
模式一:连续AE分组
同一个受试者、同一个PT的多次AE——如果前一事件的结束日紧接后一事件的开始日(相邻),视为同一段连续事件。需要给它们打上相同的groupid。
解法:RETAIN groupid + pre_aendt
SAS
/* 连续AE分组:相邻事件 → 同一groupid */
proc sort data=ADAE4D; by USUBJID AEDECOD ASTDT; run;
data ADAE5A;
set ADAE4D;
by USUBJID AEDECOD ASTDT;
retain GROUPID PRE_AENDT;
if first.AEDECOD then do;
GROUPID = 1;
PRE_AENDT = AENDT;
end;
else do;
if PRE_AENDT = ASTDT then GROUPID = GROUPID; /* 相邻:同组 */
else GROUPID + 1; /* 不连续:新组 */
PRE_AENDT = AENDT;
end;
run;
原理:PRE_AENDT存上一个事件的结束日。当前事件的开始日==上一个结束日→相邻→同组。否则新组。GROUPID+1是SAS的SUM语句(自动retain)。
然后基于分组取统计
SAS
/* 取每组首条记录,计算首次发生时间 */
proc sort data=ADAE5A out=A; by USUBJID AEDECOD GROUPID ASTDT; run;
data A1;
set A;
by USUBJID AEDECOD GROUPID ASTDT;
if first.GROUPID;
ADUR1 = ASTDT - TRTSDT + (ASTDT >= TRTSDT); /* 首次发生天数 */
keep USUBJID AEDECOD GROUPID ADUR1;
run;
模式二:ADCM周期展开
一条合并用药记录可能同时属于第一周期和第二周期。需要展开为多行——每行代表一个周期的归属。
SAS
/* ADCM:一条记录同时属于多周期时output多行 */
data ADCM3;
set ADCM2;
length APERIODC $40;
/* 同时满足周期1和周期2 → output两次 */
if ASTDT <= TR02SDT and (AENDT = . or AENDT >= TR01SDT) then do;
APERIOD = 1;
APERIODC = '第一周期';
output;
end;
if (ASTDT <= TR02EDT or ASTDT = .) and
(AENDT >= TR02SDT or AENDT = .) then do;
APERIOD = 2;
APERIODC = '第二周期';
output;
end;
else do;
APERIOD = .;
APERIODC = '';
output;
end;
run;
模式三:ADPC BQL处理
PK浓度数据中的BQL(Below Quantification Limit)需要特殊处理。规则来自SAP,逻辑链较长:
| 情况 | 处理 |
|---|---|
| Tmax之前BQL | 设为 0 |
| Tmax之后单个BQL | 设为 缺失 |
| Tmax之后连续BQL后再出现可测浓度 | 后面的可测浓度也设为 缺失 |
| 单个BQL落在两可测浓度之间 | 设为 缺失 |
| 首次给药前缺失 | 可设为 0 |
关键是状态追踪:一旦Tmax后出现连续BQL(≥2个),after_consec_bql标志永久置1。之后所有可测浓度都处理为缺失——因为此时药物已基本清除。
模式四:seq & last.variable陷阱
按分组赋seq
SAS
/* 按visitnum内对seq赋值 */
data WANT;
set HAVE;
by USUBJID VISITNUM;
retain SEQ;
if first.VISITNUM then SEQ = 0;
SEQ + 1;
run;
⚠️ last.variable不要在if条件内使用。
如果你在
如果你在
if TRTEMFL='Y' then do;块内用if last.USUBJID——二者选不到同一位置时flag会悄然置空。last./first.变量只应在最外层无条件判断。⚠️ output是提交观测。
执行output之后对该观测的变量修改不会回溯到已输出的记录。如果你output之后再改var,已输出的那条记录不受影响。
执行output之后对该观测的变量修改不会回溯到已输出的记录。如果你output之后再改var,已输出的那条记录不受影响。
⚠️ 计算前确保所有变量非缺失。
if TRTSDT<=ASTDT<=min(TRTSDT+90, SATSTDT)——如果SATSTDT缺失,整个表达式可能出问题。先检查所有变量非缺失再计算。