MERGE:8つの方法
Merging Data Eight Different Waysより
データセットをマージする8つの方法が紹介されています。
以下のPATDATAとADVERSEの2つのデータセットをSUBJECTでマージし、
かつADVERSEのみ存在するデータを残したものをALLDATA0に格納するやり方を
例としています。
Dataset: PATDATA SUBJECT TRT_CODE 124263 A 124264 A 124265 B 124266 B Dataset: ADVERSE SUBJECT EVENT 124263 HEADACHE 124266 FEVER 124266 NAUSEA 124267 FRACTURE
方法(1)DATAステップ内でMEREGEを使う方法。
一番ポピュラーなやりかたですね。
DATA alldata0; MERGE adverse (in=a) patdata (in=b); BY subject; IF a; RUN;
(2)PROC SQLでJOIN句で連結する方法です。
PROC SQL; CREATE TABLE alldata0 AS SELECT a.*, b.trt_code FROM adverse a LEFT JOIN patdata b ON a.subject=b.subject; QUIT; RUN;
(3)SETステートメントでKEYオプションを使う方法。
こんなやり方もあったんですね。知りませんでした。
DATA alldata0; SET adverse; SET patdata KEY=subject /UNIQUE; DO; IF _IORC_ THEN DO; _ERROR_=0; trt_code=''; END; END; RUN;
(4)PATDATAから文字フォーマットを作り出して、それをADVERSEデータセットに当てる方法。
DATA fmt; RETAIN fmtname 'TRT_FMT' type 'C'; SET patdata; RENAME subject=start trt_code=label; RUN; PROC FORMAT CNTLIN=fmt; RUN; DATA alldata0; SET adverse; ATTRIB trt_code LENGTH=$1 LABEL='Treatment Code'; trt_code=PUT(subject,$trt_fmt.); RUN;
(5)PATDATAからハッシュテーブルを作って、ADVERSEデータセットにヒット差せる方法。
ただしSAS9.1以降でないとできないそうです。
DATA alldata0; IF _n_=0 THEN SET patdata; IF _n_=1 THEN DO; DECLARE HASH _h1 (dataset: "PATDATA"); rc=_h1.definekey("SUBJECT"); rc=_h1.definedata("TRT_CODE"); rc=_h1.definedone(); call missing(SUBJECT,TRT_CODE); END; SET adverse; rc=_h1.find(); IF rc^=0 THEN trt_code=" "; DROP rc;; RUN;
(6)配列を使う方法。
ここまでするんだったら、個人的には普通にMERGEかPROC SQLを使った方が良い気がしますけど・・・
DATA _null_; SET sashelp.vtable; WHERE libname='WORK'; WHERE ALSO memname in('PATDATA','ADVERSE'); CALL SYMPUT('X'||memname,put(nobs,8.)); RUN; DATA alldata0; LENGTH trt_code $1; ARRAY f{&xpatdata.,2} $6 _TEMPORARY_; DO i=1 TO &xpatdata.; SET patdata (RENAME=(trt_code=trt_code_dict)); f{i,1}=PUT(subject,6.); f{i,2}=trt_code_dict; END; DO i=1 TO &xadverse.; SET adverse; trt_code=''; DO j=1 TO &xpatdata.; IF subject=INPUT(f(j,1),best.) THEN DO; trt_code=f{j,2}; OUTPUT; END; IF ^MISSING(trt_code) THEN LEAVE; END; IF MISSING(trt_code) THEN OUTPUT; END; DROP i j trt_code_dict; RUN;
(7)MODIFYステートメントを使う方法
なんだかかえって何をしているのかわかりづらくなってしまう気がします。
DATA adverse; DO p = 1 TO totobs; _IORC_ = 0; SET patdata POINT=p NOBS=totobs; DO WHILE(_IORC_=%SYSRC(_SOK)); MODIFY adverse KEY=subject; SELECT (_IORC_); WHEN (%SYSRC(_SOK)) DO; /*MATCH FOUND*/ SET patdata POINT=p; trtc=trtcode; REPLACE; END; WHEN (%SYSRC(_DSENOM)) _ERROR_ = 0; /*NO MATCH FOUND*/ END; OTHERWISE DO; /*A MAJOR PROBLEM SOMEWHERE*/ PUT 'ERROR: _IORC_ = ' _IORC_ / 'PROGRAM HALTED.'; _ERROR_ = 0; STOP; END; END; END; END; STOP; RUN;
(8)最後はCALL EXECUTEを使う方法
DATA _null_; SET patdata; CALL EXECUTE("DATA alldat;"|| " SET adverse;"|| " WHERE subject='"||STRIP(subject)||"';"|| " trt_code='"||STRIP(trt_code)||"';"|| "PROC APPEND BASE=alldata0 DATA=dat0 FORCE;"|| "RUN;");; RUN;