ラベル CDISC の投稿を表示しています。 すべての投稿を表示
ラベル CDISC の投稿を表示しています。 すべての投稿を表示

2018年7月27日金曜日

Hashオブジェクトは、CDISCに係るSASプログラミングと相性バッチリ




今回は製薬業界でのお話になります。


CDISC関連のSASプログラミング(SDTMやADaMのデータセット作成)では、よく以下のような変数を導出します。

・他のデータセットから変数値を取得
・他のデータセットに条件に合うレコードが存在する場合「Y」、 のようなフラグ変数の導出
・他のデータセットの特定レコードの最小値・最大値・合計・カウントなどの取得

これらは通常、SQL, MEANS, FREQ, TRANSPOSE, DATAステップ等を組み合わせて導出するんですが、Hashオブジェクトを使うと、すべてまとめて1回のDATAステップで導出する事も可能です。



(Hashオブジェクトがどんなものか知りたい方はデータステップ100万回のSASYAMAさんが詳しく解説をされてるので、そちらをご覧ください)

ハッシュオブジェクトの世界① (データステップ100万回)
http://sas-tumesas.blogspot.com/2014/07/blog-post_11.html




今回は、CDISC対応でのHashオブジェクトの利用例を紹介します。
以下は変数USUBJIDをキーに、他のデータセットから条件に合うレコードの変数を引っ張ってくるマクロです。

%macro m_find( DS= , WH=, VAR=, VARLEN= );
    /*-----------------------------------------------------------------------
       DS     =   対象のデータセット ,
       WH    =   WHERE条件 ,
       VAR   =   引っ張ってくる変数
       VARLEN   =   引っ張ってくる変数に設定するLENGTH
   -----------------------------------------------------------------------*/

   %local  _index;
   %let  _index = &sysindex;

   _runobs&_index + 1;
   drop _runobs&_index;

   if _runobs&_index = 1 then do;
      length &VAR &VARLEN;
      dcl hash _hash&_index( dataset:"&DS( where = (" || %sysfunc(quote(&WH)) || "))", duplicate:"e" );
      _hash&_index..definekey( "USUBJID" );
      _hash&_index..definedata( "&VAR" );
      _hash&_index..definedone();
   end;

   if _hash&_index..find() ^= 0 then call missing( &VAR );
%mend;




ではマクロの使用例も見てみましょう。

* 適当なサンプルデータ ;
data DM;
   USUBJID = "001";
run;





data SUPPDM;
   USUBJID = "001";  QNAM = "SAFFL";  QVAL = "Y";
   output;
   USUBJID = "001";  QNAM = "FASFL";  QVAL = "Y";
   output;
run;








* マクロ使用例 ;
data ADSL;
   set DM;

   *** SAFFL ******;
   %m_find( ds=SUPPDM, wh=QNAM="SAFFL", var=QVAL, varlen=$200 )

   length SAFFL $1.;
   SAFFL = QVAL;
run;



データステップ中に、SUPPDM.QNAM="SAFFL"の時のQVALを取得しています。
このマクロはシンプルで十分使えますが、もっと作りこめば、最強マクロにもなり得ます。



2017年10月5日木曜日

【CDISC】変数 [--DTC] から、ADTM, ADT, ATM への変換



CDISC関連の話。


変数「--DTC」を、ADaM変数「ADTM」「ADT」「ATM」に変換するときの、ISO8601のフォーマットと書き方を載せときます。




[--DTC] が日付のみ (時刻を含まない) の場合


※以下の例は「2017」「2017-10」等の、日付が揃っていないデータは想定していません

data DT1;

    LBDTC = "2017-10-03";

    ADT    =  input( LBDTC, e8601da. );

run;





[--DTC] が日時の場合


※以下は想定していません。
・日時が揃っていないデータ(「2017-10-03」「2017-10-03T09」等)
・秒の小数部分が含まれているデータ(「2017-10-03T09:10:12.345」等)

※以下リンクの記事に紹介してるバグにも注意。
【SAS9.3以前のBug】E8601DTインフォーマットで正しく変換できないことがある。


data DT1;

    LBDTC = "2017-10-03T09:10:00";

    ADTM =  input( LBDTC, e8601dt. );
    ADT    =  input( LBDTC, e8601da. );
    ATM    =  timepart( input( LBDTC, e8601dt. ) );

run;

・ATMだけいったん日時変換してから、TIMEPART関数で時刻部分をとりだしています。




以上、自分用のメモ記事でした。

2017年2月20日月曜日

SASデータセットをXPTファイルに変換する方法




SASデータセットをXPT(XPORT)という移送形式ファイルに変換する方法。



今回のサンプルデータ


MYSASというライブラリを作り、そこにデータセットADSLを格納しときます。

libname MYSAS "適当なパス";

data ADSL (label="SUBJECT LEVEL ANALYSIS DATASET");
   USUBJID="aaa";
run;

proc sort data=ADSL out=MYSAS.ADSL;
   by USUBJID;
run;





XPTファイルに変換するプログラム


以下プログラムを実行するとログにWARNINGが出るかもしれません。
「制限事項」のとこで補足説明してるので今は無視してください。

libname MYXPT xport "XPTファイルを格納するパス\adsl.xpt";

proc copy in=MYSAS out=MYXPT memtype=data;
   select ADSL;
run;

  • libnameでXPTファイルを格納するライブラリ参照を定義。ここではXPTファイル名を含むフルパスを指定する。
  •  proc copyでMYSAS.ADSLをライブラリMYXPTに格納。





制限事項


SASデータセットがSORTプロシジャでソートしてある場合、内部的にSORT情報が保持されており、この状態でXPT変換すると以下のようなWARNINGが表示されます。

proc sort data=MYSAS.ADSL;
   by USUBJID;
run;

libname MYXPT xport "XPTファイルを格納するパス\adsl.xpt";
proc copy in=MYSAS out=MYXPT memtype=data;
   select ADSL;
run;

ログ
WARNING: エンジンXPORTはSORTEDBY処理をサポートしていません。SORTEDBY情報はコピーできません。


ログに出てる通り、XPTではSORT情報が持たせられません。
WARNINGは出ているけどSORT情報がなくなっただけでXPTファイルはちゃんと出来ています。


このWARNINGが嫌であれば、この記事の最初のMYSAS.ADSLを作るプログラムのとこでSORTプロシジャにSORTEDBYオプションを追記すると、SORT情報を消すことができます。

proc sort data=ADSL out=MYSAS.ADSL (sortedby=_null_);
   by USUBJID;
run;

out=にこのオプションを指定するのがポイントです。



その他の制限。
  • 変数名は8文字以内
  • 変数ラベルの長さは40まで
  • データセットラベルも長さ40まで・・・など




製薬業界でのCDISC絡みの話。(2017/02/17現在での話)

CPORTプロシジャでも移送ファイル(CPTファイル)に変換できますが、
PMDAからでてる「技術的ガイドについて」という通知には「CPORT Procedureは使用しないこと」という記述があるのでご注意ください。