“人生若只如初见”,或许是针对AE合并的感慨,第一次做AE时是不需要合并的,后来需要合并时,每每都在感慨,并且为之付出为数不多的头发。
针对consecutive event-连续AE合并的时间处理,目前见到的数据集命名为ADAEGRD,如果在合并时只是进行时间比较,可以用retain、lag等进行观测提前或者滞后,然后用提前或滞后的数据进行比较,而如果是要对提前或滞后的数据进行处理并将处理后的数据传递,则只能使用retain这一个功能,在合并AE时,对时间的处理也同时进行其他相关变量如毒性等级的处理。
使用retain处理后续时间,比如上一条结束比下一条结束时间还晚,则需要将下一条结束时间修改为更晚的时间(上一条的时间),如果是正常的下一条时间更晚,则不去处理。
by usubjid aedecod aestdtc astdt asttm aendt aentm aetoxgrn astdtf aendtf;retain aendt_ aentm_ aendtm_ aendtf_ aeendtc_ end_flag_;if first.aedecod then do; aendt_ = aendt; aentm_ = aentm; aendtm_ = aendtm; aendtf_ = aendtf; aeendtc_ = aeendtc; end_flag_ = end_flag;end;else do;if nmiss (aendt, aendt_) = 0 and astdt - aendt<= 1 then do; aendt = aendt_; aentm = aentm_; aendtm = aendtm_; aendtf = aendtf_; aeendtc = aeendtc_; end_flag_ = end_flag_; if end_flag_ = 1 and end flag = 1 then put "USER WARN" "ING:" usubjid aedecod " has issue for ae end date, please check. " if aendt ne aendt_ then do; aendt = max (aendt, aendt_); if aendt = aendt_ then do; if end_flag = 0 then do; aentm = aentm_; aendtm = aendtm_; aeendtc = aeendtc_; aendtf = aendtf_; end;
相对于不处理时间,只是迭代上一次的结果,并且可能会取其中更为合适的结果(比如grade取更大值),则使用如下方式:
array a(*) aestdtc astdtf lstpravs aetoxgr arel; array aa(*) astdt asttm astdtm end_flag; array b(*) $ 200 aestdtc_n astdtf_n lstpravs_n aetoxgr_n arel_n; array bb(*) 8 astdt_n asttm_n astdtm_n end_flag_n;do i = 1 to dim(a); retain aestdtc_n astdt_n asttm_n astdtm_n astdtf_n lstpravs_n aetoxgr_n arel_n end_flag_n; if i in (1 2 3) then do; if retain_flag = 1 then do; b(i) = a(i); bb(i) = aa(i); end; else do; b(i) = strip(b(i)); bb(i) = bb(i); end; end; if i = 4 then do; if retain_flag = 1 then do; b(i) = a(i); bb(i) = aa(i); end; else do; b(i) = strip(b(i)); if cmiss(b(i), a(i)) = 0 then b(i) = strip(put(max(input(b(i), best.), input(a(i), best.)), best.)); bb(i) = max(aa(i), bb(i)); end; end; if i = 5 then do; if retain_flag = 1 then do; b(i) = a(i); end; else do; b(i) = strip(b(i)); if b(i) = 'NOT RELATED' and a(i) = 'NOT RELATED' then b(i) = 'NOT RELATED'; else if b(i) = 'NOT RELATED' and a(i) = 'RELATED' then b(i) = 'RELATED'; else if b(i) = 'RELATED' and a(i) = 'NOT RELATED' then b(i) = 'RELATED'; else if b(i) = 'RELATED' and a(i) = 'RELATED' then b(i) = 'RELATED'; end; end; if i ne 5 then aa(i) = bb(i); a(i) = b(i); end;drop i;
总结来说,整体思路就是使用retain这一功能,retain一个新变量,在合适的地方用旧变量赋值给新变量,再将新变量赋值给旧变量,如此就可以将上一条的结果保留到下一条观测中,比如:
retain a;if first.subjid then a = old_a;else a = a; old_a = a;run;
此处也需要提醒一下,在处理判别AE分组时,除了使用flag来分别外,可以使用retain结合数字来分类,比如第一条连续AE值为1,第二条连续AE为2,第三条连续AE为3,而不是单纯只是用flag来区分,使用数字在某些时候可以更快更方便去判断和处理数据,相较于用很多个flag来判断和处理,这种分类思路甚至有时候也可以用SQL处理后续步骤,数字也可以用其它的值来代替。
AE在合并的时候,思考的一些情况都比较理想化,容易考虑不到一些常见但是程序逻辑不会判定的到的情况,比如连续AE中的某一条的结束时间甚至比记录的该连续AE的最后一条的结束时间还晚,如此在处理的时候很容易判断错误,尤其是需要分dose进行判断处理的情况,本来应该合并为一条,结果因为逻辑错误合并成了多条,此情此景,不是经验丰富的人在审阅数据集或者输出时真不一定会发现错误。
另外还有比较常见的记录,连续AE在同一天发生毒性等级的变化,但是收集时间的时候有一条有日期没有时间点(即有date没有time),比如实际后记录的AE的开始时间只有date,前一条有时间且日期也是同一天,那在排序时以date和time(即DTC或者DTM)前一条很容易排到后面,在此基础上处理数据,合并后的开始时间可能就取到后记录的开始时间了。这样处理不是很确定是否严谨,以及这种处理是否更为保守。处理方法也比较简单,在astdt之后asttm之前加上recordnumber/recordposition排序(通常做进了aespid),可以保证实际记录顺序与处理前的数据排序一致,但此方法待验证。
领取专属 10元无门槛券
私享最新 技术干货