*===== 6章:SASマクロ ;
*--- 6.1 ;
*--- Example 1 ;
options mprint ;
data DT ;
input X Y ;
cards;
10 20
12 40
15 32
;
run ;
*--- SASマクロの定義 ;
%macro PRINT_DS ;
proc print data=DT ;
run ;
%mend PRINT_DS ;
*--- SASマクロの定実行 ;
%PRINT_DS ;
*--- 6.2 ;
*--- マクロ変数 ;
options mprint symbolgen ;
%macro PRINT_DS2(DSN) ;
proc print data=&DSN. ;
run ;
%mend PRINT_DS2 ;
%PRINT_DS2(DT) ;
*--- 複数のマクロ変数 ;
options mprint symbolgen ;
data DT1 ;
input TREAT $ N ;
cards;
薬剤A 15
薬剤B 15
;
run ;
data DT2 ;
input GENDER $ N ;
cards;
男性 10
女性 20
;
run ;
%macro PRINT_DS3(DSN1,DSN2) ;
proc print data=&DSN1. ; run ;
proc print data=&DSN2. ; run ;
%mend PRINT_DS3 ;
%PRINT_DS3(DT1,DT2) ;
%PRINT_DS3(DSN1=DT1,DSN2=DT2) ;
*--- 初期値の指定 ;
%macro PRINT_DS3(DSN1=DT1,DSN2=DT2) ;
proc print data=&DSN1. ; run ;
proc print data=&DSN2. ; run ;
%mend PRINT_DS3 ;
%PRINT_DS3 ;
*--- %let,%put ;
*--- 1 ;
%let VARIABLE = WEIGHT ;
%put マクロ変数VARIABLEに格納されている値は &VARIABLE です。 ;
*--- 2 ;
%let VARIABLE = WEIGHT ;
data &VARIABLE ;
ID = 1 ;
WGT = 70 ;
run ;
*--- 3 ;
%let X1 = 2 ;
%let X2 = 3 ;
%let X3 = %eval(&X1 + &X2) ;
%put *** &X1 + &X2 = &X3 *** ;
*-- call symput ;
data _null_ ;
call symput('MV1','SYMPUT') ; *--- 文字列をそのまま格納 ;
X1 = 'SYMPUT2' ;
call symput('MV2',X1) ; *--- X1の値を格納 ;
X2 = 10 ;
call symput('MV3',compress(put(X2,best.))) ; *--- X2を文字列に変換して格納 ;
X3 = '4' ;
call symput('MV'||X3,'TEST') ; *--- マクロ変数MV4に文字列を格納 ;
run ;
*--- マクロ変数の値を確認 ;
%put MV1: &MV1 MV2: &MV2 MV3: &MV3 MV4: &MV4 ;
*--- symget関数 ;
*--- 使用例1 ;
%let A = TEST ;
data _SYMGET ;
VALUE = symget('A') ;
run ;
proc print data=_SYMGET ; run ;
*--- 使用例2 ;
%let A1 = VAL1 ;
%let A2 = VAL2 ;
data VAL ;
input X $ ;
cards;
A1
A2
;
run ;
data _SYMGET2 ;
set VAL ;
VALUE = symget(X) ;
run ;
proc print data=_SYMGET2 ; run ;
*--- 自動マクロ変数 ;
data _SYS ;
x=1 ;
run ;
%put SYSDATE: &SYSDATE ;
%put SYSDATE9: &SYSDATE9 ;
%put SYSDSN: &SYSDSN ;
%put SYSERR: &SYSERR ;
%put SYSLAST: &SYSLAST ;
%put SYSSCPL: &SYSSCPL ;
%put SYSVER: &SYSVER ;
*--- globalとlocal ;
%global X ;
%macro LG ;
%let X = GLOBAL ;
%local Y ;
%let Y = LOCAL ;
%put Y: &Y ;
%mend LG ;
%LG ;
%put X: &X ;
*--- sqlプロシジャintoステートメント ;
*--- 1 ;
data INTO1 ;
X = "INTO" ;
run ;
proc sql noprint ;
select X into: _X1 from INTO1 ;
quit ;
%put _X: &_X1 ;
*--- 2 ;
data INTO2 ;
input X $ @@ ;
cards;
a b c
;
run ;
proc sql noprint ;
select X into: _X2 separated by ',' from INTO2 ;
quit ;
%put _X2: &_X2 ;
*--- 3 ;
data INTO3 ;
input Y Z $ ;
cards;
1 a
2 b
3 c
;
run ;
proc sql noprint ;
select Y,Z into: _Y separated by "," , : _Z separated by "|"
from INTO3 ;
quit ;
%put &_Y ;
%put &_Z ;
*--- 4 ;
proc sql noprint ;
select catx('=',compress(put(Y,best.)),quote(compress(Z))) into: FMT separated by " "
from INTO3 ;
quit ;
%put FMT: &FMT ;
proc format ;
value ABCFMT &FMT ;
run ;
*--- 6.3 %ifステートメント ;
*--- 1 ;
options mprint symbolgen mlogic ;
%macro PRINT_IF(FLAG=) ;
proc print data=%if &FLAG=1 %then DT1 ;
%else %if &FLAG=2 %then DT2 ;;
run ;
%mend PRINT_IF ;
%PRINT_IF(FLAG=1) ;
%PRINT_IF(FLAG=2) ;
*--- 2 ;
options mprint symbolgen mlogic ;
data BP ;
input ID DBP SBP ;
cards;
1 80 123
2 90 142
3 83 115
4 77 106
5 95 150
6 85 132
7 65 105
8 72 127
9 88 140
10 98 155
;
run ;
%macro MEANS_PRINT(FLAG=) ;
%if &FLAG = 1 %then %do ;
proc means data=BP ; var DBP SBP ; run ;
%end ;
%if &FLAG = 2 %then %do ;
proc print data=BP ; run ;
%end ;
%mend MEANS_PRINT ;
%MEANS_PRINT(FLAG=1) ;
%MEANS_PRINT(FLAG=2) ;
*--- 6.4 %doステートメント ;
*--- %do - %end ;
data DO1 ;
input AREA $ AIRTEMP @@ ;
cards;
東京都 21 大阪府 23 沖縄県 28
;
run ;
data DO2 ;
input AREA $ HUMIDITY @@ ;
cards;
東京都 41 大阪府 58 沖縄県 84
;
run ;
data DO3 ;
input AREA $ POP @@ ;
cards;
東京都 20 大阪府 50 沖縄県 90
;
run ;
%macro DO_PRINT ;
%do I =1 %to 3 %by 1 ;
proc print data=DO&I ; run ;
%end ;
%mend DO_PRINT ;
%DO_PRINT ;
*--- %do %while - %end ;
%macro DO_WHILE ;
%let I = 1 ;
%do %while(&I <= 3) ;
proc print data=DO&I ; run ;
%let I = %eval(&I + 1) ;
%end ;
%mend DO_WHILE ;
%DO_WHILE ;
*--- %do %until - %end ;
%macro DO_UNTIL ;
%let I = 1 ;
%do %until(&I > 3) ;
proc print data=DO&I ; run ;
%let I = %eval(&I + 1) ;
%end ;
%mend DO_UNTIL ;
%DO_UNTIL ;
*--- 6.5 引用符 ;
%let A = Variable ;
data QUOTE ;
X1='単引用符: &A' ;
X2="二重引用符: &A" ;
run ;
title1 '単引用符: &A' ;
title2 "二重引用符: &A" ;
proc print data=QUOTE ; run ;
title ;
*--- 6.6 マクロ関数 ;
*--- 計算 ;
%let A = 4.3 ;
%let B = 3 ;
%let C = %sysevalf(&A*&B) ;
%put *** &A * &B = &C *** ;
*--- マスキング ;
*--- %str,%nrstr ;
%let PRINT = %str(proc print data=STR ; run ;) ;
%let LABEL = %nrstr(A&B) ;
%put *** &PRINT *** ;
%put *** &LABEL *** ;
%let PRINT = proc print data=STR ; run ; ;
%let LABEL = A&B ;
%put *** &PRINT *** ;
%put *** &LABEL *** ;
*--- %quote,%bquote ;
%let A = apple ;
%let B = car ;
%let X1 = %quote(This is an &A..) ;
%let X2 = %bquote(It's a &B..) ;
%put &X1 ;
%put &X2 ;
*--- %sysfunc ;
*--- 文字関数 ;
%let CHAR1 = %sysfunc(catx(=,A,B)) ;
%let CHAR2 = %sysfunc(compress(&))AAA ;
%let CHAR3 = %qsysfunc(compress(&))AAA ;
%put *** &CHAR1 *** ;
%put *** &CHAR2 *** ;
%put *** &CHAR3 *** ;
*--- 数値関数 ;
%let NUM1 = %sysfunc(int(1.2)) ;
%let NUM2 = %sysevalf(%sysfunc(mean(1,5,7))+%sysfunc(std(1,5,7))) ;
%let NUM3 = %sysfunc(round(&NUM2,.01)) ;
%put *** &NUM1 *** ;
%put *** &NUM2 *** ;
%put *** &NUM3 *** ;
*--- 6.7 複数のアンパサンド ;
data DT1 ;
input WGT @@ ;
cards;
80 85 74 67 72 58 66 63 51 45
;
run ;
data DT2 ;
input ABD @@ ;
cards;
88 95 87 78 81 77 90 102 99 70
;
run ;
data DT3 ;
input LDL @@ ;
cards;
150 127 110 141 102 99 135 120 85 89
;
run ;
%macro NMEANS(DATA1=,DATA2=,DATA3=,VAR1=,VAR2=,VAR3=) ;
%do I = 1 %to 3 ;
proc means data=&&DATA&I n mean stddev min median max maxdec=2 ;
var &&VAR&I ;
run ;
%end ;
%mend NMEANS ;
%NMEANS(DATA1=DT1,DATA2=DT2,DATA3=DT3,VAR1=WGT,VAR2=ABD,VAR3=LDL) ;
*--- 6.8 統計解析マクロ ;
*--- ttest ;
proc format ;
value TRTF 1 = "薬剤A" 2 = "薬剤B" ;
run ;
data WGTDT ;
do TREAT = 1 to 2 ;
do I = 1 to 10 ;
input WGT @@ ;
output ;
end ;
end ;
format TREAT TRTF. ;
cards;
80 85 74 67 72 58 66 63 51 45
75 90 70 63 88 89 56 90 83 63
;
run ;
%macro TWOSAMP_T(DATA=,VAR=,GRP=) ;
proc ttest data=&DATA ;
class &GRP ;
var &VAR ;
run ;
%mend TWOSAMP_T ;
%TWOSAMP_T(DATA=WGTDT,VAR=WGT,GRP=TREAT) ;
*--- 2x2分割表 ;
proc format ;
value HEALF 1 = "治癒" 2 = "未治癒" ;
run ;
data TESTDT ;
input TREAT HEAL NN ;
format TREAT TRTF. HEAL HEALF. ;
cards;
1 1 35
1 2 20
2 1 28
2 2 26
;
run ;
%macro FREQ_BIN(DATA=,GRP=,VAL=,W=,RD=,RR_OR=,CHI=) ;
proc freq data=&DATA ;
%if &W ne %str() %then weight &W ;;
table &GRP*&VAL / %if &RD = yes %then riskdiff ;
%if &RR_OR = yes %then relrisk ;
%if &CHI = yes %then chisq ;;
run ;
%mend FREQ_BIN ;
%FREQ_BIN(DATA=TESTDT,GRP=TREAT,VAL=HEAL,W=NN,RD=yes,RR_OR=yes,CHI=yes) ;
*--- リスク差のみ ;
%FREQ_BIN(DATA=TESTDT,GRP=TREAT,VAL=HEAL,W=NN,RD=yes,RR_OR=no,CHI=no) ;
*--- 回帰分析 ;
data WGTHGT ;
do I = 1 to 10 ;
input WGT HGT @@ ;
output ;
end ;
cards;
80 175 85 178 74 169 67 168 72 173 58 160 66 170 63 161 51 157 45 155
;
run ;
%macro REG_M(DATA=,Y=,X=,INT=yes) ;
proc reg data=&DATA ;
model &Y = &X %if &INT ne yes %then / noint ;;
run ; quit ;
%mend REG_M ;
%REG_M(DATA=WGTHGT,Y=WGT,X=HGT) ;
*--- notint ;
%REG_M(DATA=WGTHGT,Y=WGT,X=HGT,INT=no) ;
*--- 分散分析 ;
proc format ;
value TRT2F 1 = "薬剤A" 2 = "薬剤B" 3 = "薬剤C" ;
run ;
data BP ;
do TREAT = 1 to 3 ;
do I = 1 to 10 ;
input SBP_CHG @@ ;
output ;
end ;
end ;
format TREAT TRT2F. ;
cards;
-5 -6 -8 -6 0 4 -2 6 -2 3
-15 -20 -15 -12 -21 -13 -14 3 -11 -9
-7 9 11 -18 3 -12 -3 -9 -8 1
;
run ;
%macro GLM_M(DATA=,GRP=,Y=,X=,MEANS=,CONT=) ;
%if &MEANS = yes %then %do ;
proc means data=&DATA ;
class &GRP ;
var &Y ;
run ;
%end ;
proc glm data=&DATA ;
class &GRP &X ;
model &Y = &GRP &X / ss3 ;
%if &CONT ne %str() %then contrast "Contrast" &GRP &CONT / e ;;
run ; quit ;
%mend GLM_M ;
%GLM_M(DATA=BP,GRP=TREAT,Y=SBP_CHG,X=,MEANS=yes,CONT=%str(-1 1 0)) ;
*--- 生存時間解析 ;
proc format ;
value TRTF 1 = "薬剤1" 2 = "薬剤2" ;
run ;
data LIFE_EV ;
do TREAT = 1 to 2 ;
input DAYS CEN @@ ;
output ;
end ;
format TREAT TRTF. ;
cards;
85 1 112 1 38 1 55 0 148 1 188 1 140 0 123 1
88 1 96 0 112 1 87 1 76 1 156 1 78 0 198 1
;
run ;
%macro LIFETEST_M(DATA=,TIME=,CENSOR=,CENVAL=,STRATA=) ;
proc lifetest data=&DATA ;
time &TIME*&CENSOR(&CENVAL) ;
strata &STRATA ;
run ;
%mend LIFETEST_M ;
%LIFETEST_M(DATA=LIFE_EV,TIME=DAYS,CENSOR=CEN,CENVAL=0,STRATA=TREAT) ;
*--- Cox ;
%macro CON_M(DATA=,CLASS=,TIME=,CENSOR=,CENVAL=,X=,TIES=) ;
proc phreg data=&DATA ;
class &CLASS ;
model &TIME*&CENSOR(&CENVAL) = &X / ties=&TIES ;
run ;
%mend CON_M ;
%CON_M(DATA=LIFE_EV,CLASS=TREAT,TIME=DAYS,CENSOR=CEN,CENVAL=0,X=TREAT,TIES=exact) ;
*--- 例数設計: 2t ;
%macro POWER_DIFF(ALPHA=,SIDES=,DIFF=,NULLDIFF=0,SD=, POWER=,NTOTAL=) ;
proc power ;
twosamplemeans
test = diff
alpha = &AlPHA
sides = &SIDES
meandiff = &DIFF
nulldiff = &NULLDIFF
stddev = &SD
power = &POWER
ntotal = &NTOTAL ;
run ;
%mend POWER_DIFF ;
%POWER_DIFF(ALPHA=0.025,SIDES=1,DIFF=2,SD=4,POWER=0.8,NTOTAL=.) ;
%POWER_DIFF(ALPHA=0.025,SIDES=1,DIFF=1 to 5 by 1,SD=3 to 5 by 1,POWER=0.8,NTOTAL=.) ;
*--- 例数設計: proportion diff ;
%macro POWER_BIN(ALPHA=,SIDES=,GROUPPS=,NULLPDIFF=0,POWER=,NTOTAL=) ;
proc power ;
twosamplefreq
test = pchi
alpha = &ALPHA
sides = &SIDES
groupps = &GROUPPS
nullpdiff = &NULLPDIFF
power = &POWER
ntotal = &NTOTAL ;
run ;
%mend POWER_BIN ;
%POWER_BIN(ALPHA=0.05,SIDES=2,GROUPPS=(0.8 0.7), POWER=0.8,NTOTAL=.) ;
%POWER_BIN(ALPHA=0.05,SIDES=2,GROUPPS=0.8 0.85 0.9 | 0.7, POWER=0.8,NTOTAL=.) ;
*--- 例数設計: Survival Analysis ;
%macro POWER_SURV(ALPHA=,SIDES=,LABEL1=,LABEL2=,TIME1=,TIME2=,RATE1=,RATE2=,
ATIME=0.001,FTIME=,POWER=,NTOTAL=) ;
proc power ;
twosamplesurvival
test = logrank
alpha = &ALPHA
sides = &SIDES
%do I = 1 %to 2 ;
curve("&&LABEL&I") = (&&TIME&I):(&&RATE&I)
%end ;
groupsurvival = "&LABEL1" | "&LABEL2"
accrualtime = &ATIME
followuptime = &FTIME
power = &POWER
ntotal = &NTOTAL ;
run ;
%mend POWER_SURV ;
%POWER_SURV(ALPHA=0.05,SIDES=2,LABEL1=%str(薬剤A),LABEL2=%str(薬剤B),
TIME1=2,TIME2=2,RATE1=0.9,RATE2=0.8,FTIME=5,POWER=0.8,NTOTAL=.) ;
*--- 6.9 レポート作成マクロ ;
*--- データの作成 ;
data HAIKEI ;
input ID TREAT AGE GENDER SMOKE WEIGHT FPG ;
cards;
1 1 79 2 1 78.6 142
2 2 53 1 2 63.1 140
3 2 58 1 2 56.5 106
4 1 51 2 2 101.0 119
5 1 68 2 2 98.2 134
6 2 53 1 1 53.1 106
7 1 53 2 2 80.3 118
8 1 50 2 1 62.2 114
9 1 64 1 2 68.3 84
10 2 67 2 2 58.1 123
11 1 57 1 1 76.8 127
12 2 41 2 2 76.6 116
13 1 52 2 1 77.4 130
14 2 50 2 2 77.9 118
15 1 41 2 2 88.4 109
16 1 51 1 2 61.2 103
17 2 38 2 1 79.5 134
18 2 55 1 1 49.2 106
19 1 57 2 2 50.2 110
20 1 43 2 2 76.9 107
21 2 62 1 2 60.3 113
22 1 43 1 2 62.0 120
23 1 57 1 1 84.9 116
24 2 50 2 1 81.9 121
25 1 47 1 1 79.3 103
26 1 45 1 1 74.7 105
27 1 60 2 2 58.9 114
28 1 58 1 1 44.7 114
29 2 61 1 1 60.5 136
30 1 68 2 1 100.6 126
31 2 50 2 2 97.2 116
32 2 50 2 2 80.7 144
33 1 68 1 2 38.7 124
34 2 53 1 2 67.3 123
35 2 48 1 2 62.0 139
36 1 52 1 1 56.1 126
37 2 57 1 2 60.6 117
38 2 56 1 2 73.0 114
39 2 55 1 1 77.5 121
40 2 47 1 1 70.2 122
41 2 51 1 1 64.0 119
42 2 53 1 1 57.9 125
43 2 62 1 1 67.8 136
44 1 49 2 2 65.7 108
45 2 41 1 2 77.0 123
46 2 60 1 2 55.9 111
47 2 52 2 1 94.5 124
48 1 63 2 1 74.1 117
49 2 61 2 1 80.1 105
50 1 57 1 1 69.8 130
51 1 60 1 2 64.6 104
52 1 60 1 2 62.8 110
53 2 65 2 2 72.0 110
54 2 46 1 2 82.9 111
55 2 50 2 2 88.2 129
56 1 59 1 2 58.9 144
57 1 51 1 2 59.5 120
58 2 57 1 2 52.8 124
59 2 58 2 1 84.7 109
60 2 71 2 2 60.6 103
;
run ;
*--- 要約統計量のレポート ;
%macro SUM_STAT(DATA=,GRP=,VAR=,VARLABEL=,STAT=,STATF=) ;
*--- 1. 統計量のカウント,キーワードとフォーマットの抽出 ;
%let I = 1 ;
%do %while(%scan(&STAT,&I) ne %str()) ;
%let STAT_N = &I ;
%let STAT&I = %scan(&STAT ,&I) ;
%let STATF&I = %scan(&STATF,&I,%str( )) ;
%let I = %eval(&I + 1) ;
%end ;
*--- 2. 要約統計量の算出 ;
proc summary data=&DATA nway ;
class &GRP ;
var &VAR ;
output out=_OUT(drop=_FREQ_ _TYPE_)
%do J = 1 %to &STAT_N ;
&&STAT&J = &&STAT&J
%end ;;
run ;
*--- 3. データセットの転置: 要約統計量を縦,各群を横に展開 ;
proc transpose data=_OUT out=_OUT_T prefix=GRP ;
var %do J = 1 %to &STAT_N ; &&STAT&J %end ;;
id &GRP ;
run ;
*--- 4. フォーマットの割り当てと文字変数への変換 ;
data RES_CONT ;
length LABEL _NAME_ _RES1 _RES2 $20. ;
set _OUT_T ;
LABEL = "&VARLABEL" ;
%do K = 1 %to &STAT_N ;
if _NAME_ = "&&STAT&K" then do ;
_RES1 = put(GRP1,&&STATF&K) ;
_RES2 = put(GRP2,&&STATF&K) ;
end ;
%end ;
keep LABEL _NAME_ _RES1 _RES2 ;
run ;
*--- 5. レポート作成 ;
proc report data=RES_CONT nowd ;
column LABEL _NAME_ _RES1 _RES2 ;
define LABEL / order "項目" ;
define _NAME_ / display "要約統計量" ;
define _RES1 / display "薬剤1" style={just=r} ;
define _RES2 / display "薬剤2" style={just=r} ;
run ;
%mend SUM_STAT ;
%SUM_STAT(DATA=HAIKEI,GRP=TREAT,VAR=WEIGHT,VARLABEL=%str(Weight(kg)),
STAT=n mean stddev min median max,
STATF=8. 8.2 8.3 8.1 8.2 8.1) ;
*--- カテゴリ変数のレポート ;
%macro SUM_CAT(DATA=,GRP=,VAR=,VARLABEL=,VARF=) ;
*--- 1. 例数とパーセントを算出 ;
ods listing close ;
proc tabulate data=&DATA out=_OUT ;
class &GRP &VAR ;
table &GRP,&VAR*(n rowpctn) ;
run ;
ods listing ;
*--- 2. N(%)とするために文字変数に変換 ;
data _OUT2 ;
set _OUT ;
_RES=put(N,best.)||"("||put(pctn_10,6.1)||")" ;
run ;
proc sort data=_OUT2 ; by &VAR ; run ;
*--- 3. データセットの転置: N(%)を縦,各群を横に展開 ;
proc transpose data=_OUT2 out=_OUT_T prefix=_RES ;
by &VAR ;
var _RES ;
id &GRP ;
run ;
*--- 4. 各カテゴリへのフォーマットの割り当て ;
data RES_CAT ;
length LABEL _NAME_ $20. ;
LABEL="&VARLABEL" ;
set _OUT_T ;
_NAME_ = left(put(&VAR,&VARF..)) ;
keep LABEL _NAME_ _RES1 _RES2 ;
run ;
*--- 5. レポート作成 ;
proc report data=RES_CAT nowd ;
column LABEL _NAME_ _RES1 _RES2 ;
define LABEL / order "項目" ;
define _NAME_ / display "カテゴリ" ;
define _RES1 / display "薬剤1" style={just=r} ;
define _RES2 / display "薬剤2" style={just=r} ;
run ;
%mend SUM_CAT ;
proc format ;
value GENDERF 1="Male" 2="Female" ;
run ;
%SUM_CAT(DATA=HAIKEI,GRP=TREAT,VAR=GENDER,VARLABEL=Gender,VARF=GENDERF) ;