CDISC準拠のADaMデータの解析プログラムの紹介
臨床試験のデータ解析をSASで行う例
有害事象の集計や臨検値の集計は、ほとんど同じ
rtfやexcel出力まではやらないが、出力直前のデータまでをなんとかSQLでやってみる
そうすればRやpythonなど他の言語でも再現しやすい
臨検値の要約統計量算出について
https://qiita.com/saspy/items/8fa79567807682b8b55c
CDISC知らない人への補足
CDISC準拠のADaM.ADSLとADaM.ADAEから有害事象の集計(SOC/PTごと)をする
ADSLは1人1行で、なんの薬飲んだかとかその人自身の情報が入ってる
今回は、各グループに何人いるのか、分母の計算に使用
ADAEは、発生した有害事象のデータ
※発生のY,Nのフラグがあるわけではなく、むしろYだけ抽出した感じ
詳しくは、ADaM IGとかCDISCとかでググってください
SOC/PT:有害事象をグループ分けしたときの、大きい分類、小さい分類
MedDRAでググるといいかも
AE集計をSQLだけでやってみた!
ADSLとADAEから有害事象(AE)の集計を行う
SAFFLとTRTEMFLを抽出条件、それ以外を使う場合はマクロ変数Whereに指定
sortは、IAO順(マクロ変数に変数名をいれる)、SOCコード順、PTコード順
AE集計は基本同じなので、マクロ化してみた
libname
libname adam "ADaMのデータセットのフォルダパス" access = readonly;
AE集計マクロ
%macro AE_Macro(IAO = , Where = %str());
%* TRT01ANのmin,max *;
proc Sql noprint;
select min( TRT01AN ) into : Min_N trimmed from adam.ADSL where SAFFL = "Y";
select max( TRT01AN ) into : Max_N trimmed from adam.ADSL where SAFFL = "Y";
quit;
%let TRT_N = %sysevalf( &Max_N. - &Min_N. + 1 );
%put 群の数:&TRT_N.;
proc Sql noprint;
%* 全体の集計 *;
create table work.AE_ALL as
select
TRTAN , TRTA , BUNBO ,
count( distinct USUBJID ) as REISUU ,
count( USUBJID ) as KENSUU ,
cats( calculated REISUU ) || " (" || put( round( calculated REISUU / BUNBO * 100 , 1e-1 ) , 5.1 ) || ") [" || cats( calculated KENSUU ) || "]" as OUT length = 50
from
( select A.* , B.BUNBO
from adam.ADAE( where = ( SAFFL = "Y" and TRTEMFL = "Y" %if %length( &Where. ) > 0 %then and &Where.; ) ) as A
left join
( select TRT01AN , TRT01A , count( USUBJID ) as BUNBO
from adam.ADSL( where = ( SAFFL = "Y" ) )
group by TRT01AN, TRT01A
) as B
on A.TRTAN = B.TRT01AN and A.TRTA = B.TRT01A
)
group by TRTAN , TRTA , BUNBO;
%* SOCごとの集計 *;
create table work.AE_SOC as
select
&IAO. , AESOCCD , AESOC , TRTAN , TRTA , BUNBO ,
count( distinct USUBJID ) as REISUU,
count( USUBJID ) as KENSUU,
cats( calculated REISUU ) || " (" || put( round( calculated REISUU / BUNBO * 100 , 1e-1 ) , 5.1 ) || ") [" || cats( calculated KENSUU ) || "]" as OUT length = 50
from
( select A.* , B.BUNBO
from adam.ADAE( where = ( SAFFL = "Y" and TRTEMFL = "Y" %if %length( &Where. ) > 0 %then and &Where.; ) ) as A
left join
( select TRT01AN , TRT01A , count( USUBJID ) as BUNBO
from adam.ADSL( where = ( SAFFL = "Y" ) )
group by TRT01AN , TRT01A
) as B
on A.TRTAN = B.TRT01AN and A.TRTA = B.TRT01A
)
group by &IAO. , AESOCCD , AESOC , TRTAN , TRTA , BUNBO;
%* PTごとの集計 *;
create table work.AE_PT as
select
&IAO. , AESOCCD , AESOC , AEPTCD , AEDECOD , TRTAN , TRTA , BUNBO ,
count( distinct USUBJID ) as REISUU ,
count( USUBJID ) as KENSUU ,
cats( calculated REISUU ) || " (" || put( round( calculated REISUU / BUNBO * 100 , 1e-1 ) , 5.1 ) || ") [" || cats( calculated KENSUU ) || "]" as OUT length = 50
from
( select A.*, B.BUNBO
from adam.ADAE( where = ( SAFFL = "Y" and TRTEMFL = "Y" %if %length( &Where. ) > 0 %then and &Where.; ) ) as A
left join
( select TRT01AN , TRT01A , count( USUBJID ) as BUNBO
from adam.ADSL( where = ( SAFFL = "Y" ) )
group by TRT01AN , TRT01A
) as B
on A.TRTAN = B.TRT01AN and A.TRTA = B.TRT01A
)
group by &IAO. , AESOCCD , AESOC , AEPTCD , AEDECOD , TRTAN , TRTA , BUNBO;
%* 集計結果まとめ *;
create table work.STAT_RESULT as
select &IAO. , AESOCCD , AESOC , AEPTCD , AEDECOD
%do i = &Min_N. %to &Max_N. ;
, max( case when TRTAN = &i. then OUT else "0 ( 0.0) [0]" end ) as OUT&i. length = 50
%end ;
from
( select * from work.AE_ALL
outer union corr
select * from work.AE_SOC
outer union corr
select * from work.AE_PT
)
group by &IAO. , AESOCCD , AESOC , AEPTCD , AEDECOD
order by &IAO. , AESOCCD , AESOC , AEPTCD , AEDECOD;
quit;
%mend;
%AE_Macro(IAO = IAOの変数名, Where = %str());で実行(where = %str(AESER = "Y")など)
OUT1,OUT2などに例数と割合と件数の値が入る
クロスオーバー試験などには未対応
memo
全体、SOC、PTごとに計算
count( distinct A )で重複削除してAをカウントする
↑を利用して、例数と件数を算出
SQLの練習として、転置もtransposeプロシジャを使わずにやってみた
※ TRTANの値をベタ打ちするのは汎用性が低いため、マクロでループを回した
IAOの変数名はADaM IGで決まってなかった気がするので、マクロパラメータで指定する