0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

SASテクニック 臨床試験の解析1 ADaMデータから有害事象の集計をする

Last updated at Posted at 2020-07-08

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で決まってなかった気がするので、マクロパラメータで指定する

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?