1K Views
October 21, 24
スライド概要
[第10回大阪sas勉強会]
SAS言語を中心として,解析業務担当者・プログラマなのコミュニティを活性化したいです
2024年10月18日 業務で使用しているハッシュオブジェクトの紹介 リアルワールドエビデンス事業本部 RWE推進センター リアルワールドデータサイエンス部 坂尻 大樹 TEL. 06-7167-5518
目次 ・はじめに ・ハッシュオブジェクトとは ・フラグ変数の作成 ・他のデータセットから変数を取得 ・業務実用例 ・応用編:多対多の処理 ・参考資料 Copyright©EPS All rights reserved. 2
はじめに SAS9.1よりハッシュオブジェクト(メモリに展開されるデータ構造体)機能がBase SASで利用可 能となった ハッシュオブジェクトの構文は、見慣れない書き方… →発表者も初めて見た時、面を食らった →勧められたマクロが便利だったため、勉強し始めた Copyright©EPS All rights reserved. 3
ハッシュオブジェクトとは データステップ中は、基本的にSET(MERGE)したデータセットについて処理を行う →他のデータセットを参照するには、あらかじめ準備が必要 data A; set B; Bの処理 ハッシュオブジェクト run; そこで、参照したい他のデータセットをハッシュオブジェクトに格納することで、 データのやり取りが可能になる 使用するマシンのスペックに左右されるが、メモリを使用する都合上、大容量データ をハッシュオブジェクトに格納するとエラーになることがある →条件で絞る等の工夫が必要になるケースも Copyright©EPS All rights reserved. 4
業務実用例(フラグ変数の作成) 異なるデータセットの情報からフラグを作りたい →例:有害事象のデータセットから重篤な有害事象を発現した症例を抽出し、フラグを作りたい (でもデータセットのサイズも大きく、SORT→MERGEはしたくない…) →ハッシュオブジェクトのCHECKメソッドとMULTIDATA:‘Y‘を 使えば楽にできる!! →マクロ作成 Copyright©EPS All rights reserved. 5
業務実用例(フラグ変数の作成) data BACK; CASEID=1;output; CASEID=2;output; CASEID=3;output; run; 処方データの変数ROOTの「経口」「皮下」 「舌下」を参照して、BACKにフラグを立て たい… Copyright©EPS All rights reserved. 6
業務実用例(フラグ変数の作成)
/*=========================================================
FLGMAKEマクロ
---- ------ ------ ------ ------ ------ ------ ------ ------ -----データステップ中 に挿入 し、 マスター(MASTER=)で指定したデータセット
から指定 した キー(KEY =)に一 致するレコードについてフ ラグ立 てするマクロ。
MASTER
:データを持ってきた いマスターとなる データセット
KEY
:ルックアップするためのキー変数(複数 指定可 能)
FLG
:フラグを立てる変数名 を設定
WH
:条件 を設定(WH=%S TR(AEFLG ="Y "))
TYPE
:該当/非該 当 TYPE=1(1/2) TY PE=2 (1/0) TYP E=3( Y/N) TYPE=4(1/.) (デフォルトはTYPE=1)
MIS SWARN
:元データのKEY欠損 を許容するか否か(デフォルトはN(欠損 はWARNINGとして 出ます))
---- ------ ------ ------ ------ ------ ------ ------ ------ -----・SAS 9.13以上 の環 境
%MACRO FLGMAKE( MA STE R=,K EY=,FLG=,WH=,TYPE=1,MISSWARN=N);
/*設定*/
%LO CA L NAME Q KEY KEYNUM KE Y WH;
%LE T KEY=%SY SFUNC(COMPBL( &KEY.));
%LE T NAME = &S YSINDEX.;
%LE T QKE Y = %SY SFUNC( TRANWRD( %STR("& KEY.") , %STR( ) , %STR(",") ) );
%LE T KEYNUM = %SY SFUNC( CO UNT( &KEY., %STR ( ) ));
/*参照 元データ準備*/
IF 0 THEN SET & MA STE R(K EEP= &K EY);
/*IF文に ネストして使われ た際、_N_=1では危険なので念のため*/
RETA IN _N_ &NA ME 1;
/*ハッシュ設定*/
IF _N_&NAME = 1 THEN DO ;
オリジナル:201811 05 坂尻 大樹
---- ------ ------ ------ ------ ------ ------ ------ ------ -----【注意 点】
・IF文の中に ネストしての使用は不 可能です
[NG例] DATA A;
SET B;
IF XX = 1 THEN DO ;
%LO OKUP(MASTER=MAS TER , KEY =ID,VAR= A B);
END;
RUN;
【記載 例】
DATA ADSL;
SET HEA D;
%FLGMAK E(MASTER=AE,KEY =STUDY SUBJID,FL G=A EUMU,WH=%STR( AEFLG="Y") );
RUN;
============================================================*/
%IF %LE NG TH(&WH) NE 0 %THEN %DO;
DECL ARE HASH H&NAME.(DATASET :"&MAS TER( WHE RE = (" || %SY SFUNC(QUOTE(&WH.)) || ")) " , MULTIDATA:'Y');
%END;
%EL SE %DO;
DECL ARE HASH H&NAME.(DATASET:"&MAS TER.(KEEP = &KEY.)", MULTIDATA:'Y');
%END;
H&NAME..DEFINEKE Y(&QKE Y.);
H&NAME..DEFINEDONE();
_N_&NAME = 0 ;
DRO P _ N_&NAME.;
END;
/*フラグの変数を初 期化*/
%IF %LE NG TH(&KEY.) NE 0 %THEN %DO;
CALL MISS ING(O F &FLG.);
%END;
/*フラグ立て*/
%IF %UPCASE(&TYPE.) EQ 1 %THEN %DO;
&FLG. = IFN(H&NAME..CHECK ()=0,1,2);
%END;
%IF %UPCASE(&TYPE.) EQ 2 %THEN %DO;
&FLG. = IFN(H&NAME..CHECK ()=0,1,0);
%END;
%IF %UPCASE(&TYPE.) EQ 3 %THEN %DO;
&FLG. = IFC(H&NAME..CHECK ()=0,"Y","N");
%END;
%IF %UPCASE(&TYPE.) EQ 4 %THEN %DO;
&FLG. = IFN(H&NAME..CHECK ()=0,1,.);
%END;
/*元データのKEY欠損 を許容するか否か*/
%IF %UPCASE(&MIS SWARN.)= N %THEN %DO;
IF CMISS( OF &KEY.)>0THEN DO ;
PUTL OG "WARNING:元データ内にKEY欠損 があります。" +2 (&KEY.) (=) ;
CALL MISS ING(O F &FLG.);
END;
%END;
%MEND FLGMAKE;
Copyright©EPS All rights reserved.
7
業務実用例(フラグ変数の作成) data ADSL; set BACK; %FLGMAKE (MASTER=ADEX, KEY=CASEID, FLG=ROOT1, WH=%STR(ROOT="経口"), TYPE=4); %FLGMAKE (MASTER=ADEX, KEY=CASEID, FLG=ROOT2, WH=%STR(ROOT="皮下"), TYPE=4); %FLGMAKE (MASTER=ADEX, KEY=CASEID, FLG=ROOT3, WH=%STR(ROOT="舌下"), TYPE=4); run; マクロの引数について %FLGMAKE (MASTER=,KEY=,FLG=,WH=,TYPE=1,MISSWARN=N); MASTER :データを持ってきたいマスターとなるデータセット KEY :ルックアップするためのキー変数(複数指定可能) FLG :フラグを立てる変数名を設定 WH :条件を設定(WH=%STR(AEFLG="Y")) TYPE :該当/非該当 (デフォルトはTYPE=1) TYPE=1(1/2) TYPE=2(1/0) TYPE=3(Y/N) TYPE=4(1/.) MISSWARN :元データのKEY欠損を許容するか否か (デフォルトはN (欠損の場合、WARNINGとして出ます)) Copyright©EPS All rights reserved. 8
業務実用例(他のデータセットから変数を取得) 異なるデータセットの変数を取得したい →例:患者背景のデータセットから年齢、性別等の背景情報を取得したい (でもデータセットのサイズも大きく、SORT→MERGEはしたくない…) →ハッシュオブジェクトのDEFINEDONEメソッドを使えば楽にできる!! →マクロ化 イーピーエス 森岡さんのマクロをお借りしました。 ありがとうございます。 Copyright©EPS All rights reserved. 9
業務実用例(他のデータセットから変数を取得)) data BACK; CASEID=1;output; CASEID=2;output; CASEID=3;output; run; 患者背景データの年齢、性別を取得したい… Copyright©EPS All rights reserved. 10
業務実用例(他のデータセットから変数を取得)
/*=========================================================
lookupマクロ
---- ------ ------ ------ ------ ------ ------ ------ ------ -----データステップ中 に挿入 し、 マスター(maste r=)で指定したデータセット
から指定 した キー(key=)に一 致するレコードについて
必要 な変数(var=)をマスターから持 ってきて結 合するマクロ。
master
:データを持ってきた いマスターとなる データセット(keyで一意の必要 あり)
key
:ルックアップするためのキー変数(複数 指定可 能)
var
:マスターから持 ってきたい変数 (複 数指定 可能)
warn
:マスターに 該当キー値が見つからなかった場 合のログ へのWARNINGの出力(Y/N)
flg
:マスターに 該当キーが見 つかった場合 に1を返す変数 名を設定
---- ------ ------ ------ ------ ------ ------ ------ ------ -----・SAS 9.13以上 の環 境
オリジナル:201703 01 森岡 裕
---- ------ ------ ------ ------ ------ ------ ------ ------ -----【注意点 】
・指定したキー変数でユニークになっているマスターを使 用してください。
以下 のエラーがでる場合 は、master =で指定したデータセットがkey=で指定した
変数 でユニークになっていないことが考え られ ます。
ERRO R: データセット master (ke ep= XX) を 行 X カラム XXにロードする際 に、キーの重複 が見つかりました 。
ERRO R: ハッシュデータセットのロードは、 行 X カラム XXで失敗しました。
ERRO R: DA TA STEP コンポーネントオブジェクトエラーEXECUTION フェーズ時に 中止されました。
・付与する変 数がすでにデータセットに存 在する場合 、マスターの値で上書 きし、
アンマッチのレコードはブランクで上書きされます。
・if文の中にネストしての使用は不 可能です
[NG例] da ta A;
set B;
if XX = 1 then do;
%LookUp(maste r=master , key =ID,var= a b);
end;
run;
%m acro LookUp(maste r=,key=,var=,warn=N,flg=) ;
%local name qkey qvar keyn um key var;
%let key=%sysfunc(compbl(&key));
%if %len gth(&var) ne 0 %then %do;
%let var=%sysfunc(compbl(&var));
%en d;
if 0 then se t &maste r(keep= &key &var);
%let name = &sysindex;
retain _N_&name 1;
if _N_&name = 1 then do;
%let qkey = %sysfunc( tranwrd( %str("& key") , %str( ) , %str(",") ) );
%let keyn um = %sysfunc( co unt( & key, %str ( ) ));
declare hash h&name.(dataset:"&master(keep= &ke y &var)" , duplicate:'E');
h&name..definekey(&qkey);
%if %len gth(&var) ne 0 %then %do;
h&name..definedata(all:'Y');
%en d;
h&name..definedon e();
_N_&name = 0 ;
end;
drop _N_&name ;
if h&name..find() ne 0 then do;
%if %len gth(&var) ne 0 %then %do;
call missing(of &var &flg);
%en d;
%if %upcase( &warn )= Y %then %do;
if cmiss(of &ke y) ne &keyn um +1 then putlog "WARNING:マスターに 存在しないキーのレコードです" +2 (&key.) (=) ;
%en d;
end;
%if %len gth(&flg) ne 0 %then %do;
else &flg = 1;
%en d;
%mend LookUp;
【使用例 ①】
データセットmasterからIDをキーとしてaとbをrawに結合する
data raw;
set raw;
%LookUp(maste r=master , key =ID,var= a b)
run;
【使用例 ②】
データセットmasterにIDの値をキーとして同値 があるかを判定 し、 ある場 合はF1に1を返す
data raw;
set raw;
%LookUp(maste r=master , key =ID,flg=F1)
run;
※var=を指定 してデータを取 りつつ、フラグを設 定することも 可能
data raw;
set raw;
%LookUp(maste r=master , key =ID,var= a b ,flg=F1)
run;
============================================================*/
Copyright©EPS All rights reserved.
11
業務実用例(他のデータセットから変数を取得) data ADSL; set BACK; %LOOKUP (MASTER=BASE, KEY=CASEID,VAR=AGE SEX); run; マクロの引数について %LOOKUP (MASTER=,KEY=,VAR=,WARN=,FLG=); MASTER :データを持ってきたいマスターとなるデータセット(KEYで一意の必要あり) KEY :ルックアップするためのキー変数(複数指定可能) VAR :マスターから持ってきたい変数(複数指定可能) WARN :マスターに該当キー値が見つからなかった場合のログへのWARNINGの出力(Y/N) FLG :マスターに該当キーが見つかった場合に1を返す変数名を設定 Copyright©EPS All rights reserved. 12
業務実用例(実例) 1つのデータステップ内で、異なるデータセットから何回でも結合できる(可読性も良くなります) date ADSL; set BACK; %LOOKUP (MASTER=SUBSET1 ,KEY=CASEID ,VAR=SAF SAF1 SAF2 EFF EFF1 EFF2); %LOOKUP (MASTER=SUBSET2 ,KEY=CASEID ,VAR=AESTDATE AEEDDATE); %LOOKUP (MASTER=SUBSET3 ,KEY=CASEID ,VAR=DOSEDATE DOSEID); if DOSEDATE^=. then TRTSTDATE=DOSEDATE; if DOSEDATE^=. and DOSEID in (1,2) then TRTID=1; %FLGMAKE (MASTER=SUBSET4, KEY=CASEID, FLG=DOSEFLG1, WH=%STR(200<=DOSE)); %FLGMAKE (MASTER=SUBSET4, KEY=CASEID, FLG=DOSEFLG2, WH=%STR(.<DOSE<200)); run; Copyright©EPS All rights reserved. 13
業務実用例~応用編~ (多対多の処理) %LOOKUPはキー変数が1対1、%FLGMAKEは1対1・1対多を想定 →多対多の処理はなんとかならないの? →例:薬剤の処方日と併存疾患の発現日を比較してフラグを立てたい… (どちらも1症例複数レコード…) →マクロ化検討中…(次回発表できたら…) Copyright©EPS All rights reserved. 14
業務実用例~応用編~ (多対多の処理) data DOSE; format CASEID 8. DOSEDATE YYMMDD10.; CASEID=1; DOSEDATE=INPUT("2024/1/1",YYMMDD10.); output; CASEID=1; DOSEDATE=INPUT("2024/2/1",YYMMDD10.); output; CASEID=2; DOSEDATE=INPUT("2024/1/1",YYMMDD10.); output; CASEID=2; DOSEDATE=INPUT("2024/4/1",YYMMDD10.); output; run; data MH; format CASEID 8. MHSTARTDATE MHENDDATE YYMMDD10.; CASEID=1; MHSTARTDATE=INPUT("2024/1/1",YYMMDD10.); MHENDDATE=INPUT("2024/1/31",YYMMDD10.); output; CASEID=2; MHSTARTDATE=INPUT("2024/3/1",YYMMDD10.); MHENDDATE=INPUT("2024/5/31",YYMMDD10.); output; CASEID=2; MHSTARTDATE=INPUT("2024/3/1",YYMMDD10.); MHENDDATE=INPUT("2024/4/30",YYMMDD10.); output; run; Copyright©EPS All rights reserved. 15
業務実用例~応用編~ (多対多の処理) Copyright©EPS All rights reserved. 16
業務実用例~応用編~ (多対多の処理) data SUBSET; set DOSE; ******ハッシュオブジェクトを定義; if 0 then set MH; if _n_=1 then do; dcl hash hs (dataset:"MH",multidata:"Y"); hs.definekey ("CASEID"); hs.definedata("CASEID","MHSTARTDATE","MHENDDATE"); hs.definedone(); end; do while、 do_overメソッドの組み合わせ ******ハッシュオブジェクト処理; do while(hs.do_over()=0); if .<MHSTARTDATE<=DOSEDATE<=MHENDDATE then FLG=1; else FLG=0; ループさせているため、elseでFLG=0を設定 end; すると、ループ1週目で1が立たっとしても、 ******ハッシュオブジェクト処理終了; if FLG ne 1 then FLG=0; keep CASEID DOSEDATE FLG; run; Copyright©EPS All rights reserved. ループ2週目以降で該当しなければ0になる 場合もある (同一変数内で分岐させると1→0→1→0の ように値が変動する可能性がある) 17
参考文献 (1)データステップ100万回 SAS新手一生(データステップ100万回 SAS新手一生 (sas-tumesas.blogspot.com) ) 「ハッシュオブジェクトの世界①」 「ハッシュオブジェクトの世界③ checkメソッドと、メソッドの戻り値をそのままIFC IFN関数に使う話」 「ハッシュオブジェクトの世界⑥ outputメソッド ordered」 「大半のソートは百害あって一利無しという話」 (2) SAS備忘録( SAS忘備録 (sas-boubi.blogspot.com) ) 「Hashオブジェクトは、CDISCに係るSASプログラミングと相性バッチリ 」 (3) SASユーザー総会2014(スライド 1 (sas.com) ) 「SAS ハッシュオブジェクトを利用して医薬品開発に使用するプログラムを効率化する-有害事象と併用薬、臨床検査値と途中 変更のある施設基準値のマッチングからSASプログラムコードの分析まで」 森岡裕 (4) SAS ユーザー総会2018 論文集(セッション | SAS) 「 DOSUBL関数内で生成したビューをハッシュオブジェクトに格納することによりPROC DS2の ハッシュパッケージの挙動を 擬似的に再現する方法」 森岡裕 Copyright©EPS All rights reserved. 18
経営理念 Copyright©EPS All rights reserved. 19