*--- 連続変数とカテゴリ変数が混在したレポートの作成 ;
%macro SUM_TABLE(DATA=,GRP=,GRPF=,VAR=,VARLABEL=,VARF=,VARFLAG=,STAT=,STATF=) ;
   *--- 1. 変数のカウント,変数タイプのフラグ,ラベル,フォーマットの抽出 ;
   %let I = 1 ;
   %do %while(%scan(&VAR,&I) ne %str()) ;
      %let VAR_N      = &I ;
      %let VAR&I      = %scan(&VAR ,&I) ;
      %let VARF&I     = %scan(&VARF,&I,%str( )) ;
      %let VARFLAG&I  = %scan(&VARFLAG,&I,%str( )) ;
      %let VARLABEL&I = %scan(&VARLABEL,&I,%str(,)) ;
      %let I = %eval(&I + 1) ;
   %end ; %put &VAR_N ;
   *--- 2. 統計量のカウント ;
   %let J = 1 ;
   %do %while(%scan(&STAT,&J) ne %str()) ;
      %let STAT_N = &J ;
      %let STAT&J  = %scan(&STAT ,&J) ;
      %let STATF&J = %scan(&STATF,&J,%str( )) ;
      %let J = %eval(&J + 1) ;
   %end ;
   *--- 3. 変数を1つずつ結果を作成して縦結合する ;
   %do K = 1 %to &VAR_N ;
      %if &&VARFLAG&K = 1 %then %do ; *--- 連続変数の処理 ;
         *--- 4. 要約統計量の算出 ;
         proc summary data=&DATA nway ;
             class &GRP ;
             var &&VAR&K ;
             output out=_OUT(drop=_FREQ_ _TYPE_)
             %do L = 1 %to &STAT_N ;
                &&STAT&L = &&STAT&L
             %end ;;
         run ;
         *--- 5. データセットの転置: 要約統計量を縦,各群を横に展開 ;
         proc transpose data=_OUT out=_OUT_T prefix=GRP ;
            var %do M = 1 %to &STAT_N ; &&STAT&M %end ;;
            id &GRP ;
         run ;
         *--- 6. フォーマットの割り当てと文字変数への変換 ;
         data _RES ;
            length LABEL _NAME_ _RES1 _RES2 $30. ;
            set _OUT_T ;
            LABEL = "&&VARLABEL&K" ;
            %do N = 1 %to &STAT_N ;
               %if &&STAT&N = n %then %do ;
                  if _NAME_ = "n" then do ;
                     _RES1 = put(GRP1,best.) ;
                     _RES2 = put(GRP2,best.) ;
                  end ;
               %end ;
               %else %do ;
                  if _NAME_ = "&&STAT&N" then do ;
                     _RES1 = put(GRP1,%scan(&&VARF&K,1,.).%eval(%scan(&&VARF&K,2,.)+&&STATF&N)) ;
                     _RES2 = put(GRP2,%scan(&&VARF&K,1,.).%eval(%scan(&&VARF&K,2,.)+&&STATF&N)) ;
                  end ;
               %end ;
            %end ;
            keep LABEL _NAME_ _RES1 _RES2 ;
         run ;
      %end ;
      %else %if &&VARFLAG&K = 2 %then %do ; *--- カテゴリ変数の処理 ;
         *--- 7. 例数とパーセントを算出 ;
         ods listing close ;
         proc tabulate data=&DATA out=_OUT ;
            class &GRP &&VAR&K ;
            table &GRP,&&VAR&K*(n rowpctn)  ;
         run ;
         ods listing ;
         *--- 8. N(%)とするために文字変数に変換 ;
         data _OUT2 ;
            set _OUT ;
            _RES=put(N,best.)||"("||put(pctn_10,5.1)||")" ;
         run ;
         proc sort data=_OUT2 ; by &&VAR&K ; run ;
         *--- 9. データセットの転置: N(%)を縦,各群を横に展開 ;
         proc transpose data=_OUT2 out=_OUT_T prefix=_RES ;
            by &&VAR&K ;
            var _RES ;
            id &GRP ;
         run ;
         *--- 10. 各カテゴリへのフォーマットの割り当て ;
         data _RES ;
            length LABEL _NAME_ $30. ;
            LABEL="&&VARLABEL&K" ;
            set _OUT_T ;
            _NAME_ = left(put(&&VAR&K,&&VARF&K...)) ;
            keep LABEL _NAME_ _RES1 _RES2 ; 
         run ;
      %end ;
      *--- 11. 変数の結果を一つずつ縦結合 ;
      data RES ;
         set %if &K > 1 %then RES ; _RES(in=_R) ;
         if _R then ORDER = &K ;
         _RES1 = trim(right(_RES1)) ;
         _RES2 = trim(right(_RES2)) ;
      run ;
   %end ;
   *--- 12. レポートを作成する ;
   proc report data=RES nowd ;
      column ORDER LABEL _NAME_ _RES1 _RES2 ;
      define ORDER  / order noprint ;
      define LABEL  / order "項目" ;
      define _NAME_ / display "カテゴリ" ;
      define _RES1  / display "薬剤1" ;
      define _RES2  / display "薬剤2" ;
   run ;
%mend SUM_TABLE ;

proc format ;
   value GENDERF 1="Male" 2="Female" ;
   value SMOKEF 1="Yes" 2="No" ;
run ;

%SUM_TABLE(
   DATA     = HAIKEI,
   GRP      = TREAT,
   GRPF     = TREATF,
   VAR      = %str(AGE  GENDER  SMOKE  WEIGHT  FPG),
   VARLABEL = %str(Age(years), Gender, Smoke, Weight(kg), Fasting Plasma Glucose(mg/dL)),
   VARF     = %str(8. GENDERF SMOKEF 8.1 8.),
   VARFLAG  = %str(1  2       2      1   1 ),
   STAT     = %str(n mean stddev min median max),
   STATF    = %str(0 1    2      0   1      0 )) ;

*--- ODSの出力先を追加 ;
%macro SUM_TABLE_ODS(DATA=,GRP=,GRPF=,VAR=,VARLABEL=,VARF=,VARFLAG=,STAT=,STATF=,ODSTYPE=,STYLE=) ;
   *--- 1. 変数のカウント,変数タイプのフラグ,ラベル,フォーマットの抽出 ;
   %let I = 1 ;
   %do %while(%scan(&VAR,&I) ne %str()) ;
      %let VAR_N      = &I ;
      %let VAR&I      = %scan(&VAR ,&I) ;
      %let VARF&I     = %scan(&VARF,&I,%str( )) ;
      %let VARFLAG&I  = %scan(&VARFLAG,&I,%str( )) ;
      %let VARLABEL&I = %scan(&VARLABEL,&I,%str(,)) ;
      %let I = %eval(&I + 1) ;
   %end ; %put &VAR_N ;
   *--- 2. 統計量のカウント ;
   %let J = 1 ;
   %do %while(%scan(&STAT,&J) ne %str()) ;
      %let STAT_N = &J ;
      %let STAT&J  = %scan(&STAT ,&J) ;
      %let STATF&J = %scan(&STATF,&J,%str( )) ;
      %let J = %eval(&J + 1) ;
   %end ;
   *--- 3. 変数を1つずつ結果を作成して縦結合する ;
   %do K = 1 %to &VAR_N ;
      %if &&VARFLAG&K = 1 %then %do ; *--- 連続変数の処理 ;
         *--- 4. 要約統計量の算出 ;
         proc summary data=&DATA nway ;
             class &GRP ;
             var &&VAR&K ;
             output out=_OUT(drop=_FREQ_ _TYPE_)
             %do L = 1 %to &STAT_N ;
                &&STAT&L = &&STAT&L
             %end ;;
         run ;
         *--- 5. データセットの転置: 要約統計量を縦,各群を横に展開 ;
         proc transpose data=_OUT out=_OUT_T prefix=GRP ;
            var %do M = 1 %to &STAT_N ; &&STAT&M %end ;;
            id &GRP ;
         run ;
         *--- 6. フォーマットの割り当てと文字変数への変換 ;
         data _RES ;
            length LABEL _NAME_ _RES1 _RES2 $30. ;
            set _OUT_T ;
            LABEL = "&&VARLABEL&K" ;
            %do N = 1 %to &STAT_N ;
               %if &&STAT&N = n %then %do ;
                  if _NAME_ = "n" then do ;
                     _RES1 = put(GRP1,best.) ;
                     _RES2 = put(GRP2,best.) ;
                  end ;
               %end ;
               %else %do ;
                  if _NAME_ = "&&STAT&N" then do ;
                     _RES1 = put(GRP1,%scan(&&VARF&K,1,.).%eval(%scan(&&VARF&K,2,.)+&&STATF&N)) ;
                     _RES2 = put(GRP2,%scan(&&VARF&K,1,.).%eval(%scan(&&VARF&K,2,.)+&&STATF&N)) ;
                  end ;
               %end ;
            %end ;
            keep LABEL _NAME_ _RES1 _RES2 ;
         run ;
      %end ;
      %else %if &&VARFLAG&K = 2 %then %do ; *--- カテゴリ変数の処理 ;
         *--- 7. 例数とパーセントを算出 ;
         ods listing close ;
         proc tabulate data=&DATA out=_OUT ;
            class &GRP &&VAR&K ;
            table &GRP,&&VAR&K*(n rowpctn)  ;
         run ;
         ods listing ;
         *--- 8. N(%)とするために文字変数に変換 ;
         data _OUT2 ;
            set _OUT ;
            _RES=put(N,best.)||"("||put(pctn_10,5.1)||")" ;
         run ;
         proc sort data=_OUT2 ; by &&VAR&K ; run ;
         *--- 9. データセットの転置: N(%)を縦,各群を横に展開 ;
         proc transpose data=_OUT2 out=_OUT_T prefix=_RES ;
            by &&VAR&K ;
            var _RES ;
            id &GRP ;
         run ;
         *--- 10. 各カテゴリへのフォーマットの割り当て ;
         data _RES ;
            length LABEL _NAME_ $30. ;
            LABEL="&&VARLABEL&K" ;
            set _OUT_T ;
            _NAME_ = left(put(&&VAR&K,&&VARF&K...)) ;
            keep LABEL _NAME_ _RES1 _RES2 ; 
         run ;
      %end ;
      *--- 11. 変数の結果を一つずつ縦結合 ;
      data RES ;
         set %if &K > 1 %then RES ; _RES(in=_R) ;
         if _R then ORDER = &K ;
         _RES1 = trim(right(_RES1)) ;
         _RES2 = trim(right(_RES2)) ;
      run ;
   %end ;

   *--- ODS出力 ;
   ods listing close ;
   ods &ODSTYPE file="%sysfunc(pathname(work))\temp.&ODSTYPE"
       %if &STYLE ne %str() %then style=&STYLE ;;
   *--- 12. レポートを作成する ;
   proc report data=RES nowd split="#"
        style(report)={rules=none background=white}
        style(header)={fontfamily="MS Gothic"   fontsize=10pt height=15pt
                       just=c vjust=bottom}
        style(column)={fontfamily="Courier New" fontsize=10pt height=15pt
                       vjust=c rules=none} ;
      column ORDER LABEL _NAME_ _RES1 _RES2 DEF ;
      define ORDER  / order noprint ;
      define LABEL  / order "項目" ;
      define _NAME_ / display "統計量/カテゴリ" style={width=120pt} ;
      define _RES1  / display "薬剤1" style(column)={just=r} ;
      define _RES2  / display "薬剤2" style(column)={just=r} ;
      define DEF    / computed noprint ;

      compute DEF ;
         if LABEL ne "" then do ;
            call define(_ROW_,'style','style={bordertopstyle=solid bordertopwidth=1}') ;
         end ;
      endcomp ;
   run ;

   ods &ODSTYPE close ;
   ods listing ;
%mend SUM_TABLE_ODS ;

proc format ;
   value GENDERF 1="Male" 2="Female" ;
   value SMOKEF 1="Yes" 2="No" ;
run ;

%SUM_TABLE_ODS(
   DATA     = HAIKEI,
   GRP      = TREAT,
   GRPF     = TREATF,
   VAR      = %str(AGE  GENDER  SMOKE  WEIGHT  FPG),
   VARLABEL = %str(Age(years), Gender, Smoke, Weight(kg), Fasting Plasma Glucose(mg/dL)),
   VARF     = %str(8. GENDERF SMOKEF 8.1 8.),
   VARFLAG  = %str(1  2       2      1   1 ),
   STAT     = %str(n mean stddev min median max),
   STATF    = %str(0 1    2      0   1      0 ),
   ODSTYPE  = RTF,
   STYLE    = minimal) ;

*--- スタイル属性の制御 ;
%macro REPORT_STYLE(DATA=,GRP=,GRPF=,VAR=,FRAME=,RULES=,FONT=,FSIZE=) ;
   ods listing close ;
   ods rtf file="%sysfunc(pathname(work))\temp.rtf" style=RTF ;
   *--- レポート作成 ;
   proc tabulate data=&DATA ;
      var &VAR ;
      class &GRP ;
      classlev &GRP / style={fontfamily = "MS Gothic"
                             fontsize   = &FSIZE.pt
                             background = white} ;
      table &VAR=""*(n="N"*f=best. mean="Mean"*f=8.1 stddev="SD"*f=8.2),
            &GRP=""*{style={fontfamily  = "&FONT"
                            fontsize    = &FSIZE.pt
                            background  = white}}
            / style = {frame=&FRAME rules=&RULES}
              box   = {label="" style={background=white}}
              row   = float ;
      keyword n mean stddev / style={fontfamily = "&FONT"
                                     fontsize   = &FSIZE.pt
                                     background = white} ;
      format &GRP &GRPF.. ;
   run ;
   ods rtf close ;
   ods listing ;
%mend REPORT_STYLE ;

proc format ;
   value TRTF 1 = "薬剤1" 2 = "薬剤2" ;
run ;

%REPORT_STYLE(DATA=HAIKEI,GRP=TREAT,GRPF=TRTF,VAR=WEIGHT,
              FRAME=hsides,RULES=rows,FONT=%str(Courier New),FSIZE=9) ;

*--- 2標本t検定の制御 ;
%macro SUM_TTEST(DATA=,GRP=,GRPF=,VAR=,VARLABEL=,TTEST=) ;
   proc summary data=&DATA nway ; *-- 要約統計量の算出 ;
      class &GRP ; var &VAR ;
      output out=_OUT(drop=_TYPE_ _FREQ_) n=N mean=MEAN stddev=SD ;
   run ;
   %if &TTEST = 1 %then %do ; *--- 2標本t検定の実行 ;
      ods listing close ;
      ods output Ttests=_TTEST(where=(method="Pooled")) ;
      proc ttest data=HAIKEI ; class &GRP ; var &VAR ; run ;
      ods output close ;
      ods listing ;
      data _OUT ; merge _OUT _TTEST ; run ;
   %end ;
   data _OUT ; *--- 分析変数ラベルの格納 ;
      length LABEL $20. ;
      set _OUT ;
      LABEL = "&VARLABEL" ;
   run ;
   options missing=" " ; *--- 欠測値の空白出力 ;
   ods listing close ;
   ods rtf file="%sysfunc(pathname(work))\temp.rtf" style=rtf ; *--- レポート ;
   proc report data=_OUT nowd
               style(report)={frame=hsides rules=rows}
               style(header)={background=white fontfamily="Courier New"}
               style(column)={background=white fontfamily="Courier New"} ;
      column LABEL TREAT N MEAN SD %if &TTEST=1 %then tValue Probt ; _LINE ;
      define LABEL  / order ;
      define TREAT  / display format=&GRPF.. ;
      define N      / display format=best. ;
      define MEAN   / display format=8.1 ;
      define SD     / display format=8.2 ;
      define _LINE  / computed noprint ;
      %if &TTEST=1 %then %do ;
         define tValue / display "t-value" format=8.3 ;
         define Probt  / display "p-value" format=8.3 ;
      %end ;
      compute _LINE ; *--- 1行目と2行目の間の罫線出力の制御 ;
         if LABEL ne "" then do ;
            call define('_C1_','style','style={borderbottomstyle=none}') ;
            %if &TTEST=1 %then %do ;
               call define('_C6_','style','style={borderbottomstyle=none}') ;
               call define('_C7_','style','style={borderbottomstyle=none}') ;
            %end ;
         end ;
      endcomp ;
   run ;
   ods rtf close ;
   ods listing ;
%mend SUM_TTEST ;

proc format ;
   value TRTABF 1 = "A" 2 = "B" ;
run ;

*--- t検定あり ;
%SUM_TTEST(DATA=HAIKEI,GRP=TREAT,GRPF=TRTABF,
            VAR=WEIGHT,VARLABEL=%str(Weight(kg)),TTEST=1) ;

*--- t検定なし ;
%SUM_TTEST(DATA=HAIKEI,GRP=TREAT,GRPF=TRTABF,
            VAR=WEIGHT,VARLABEL=%str(Weight(kg)),TTEST=0) ;

*--- 6.10 グラフ作成マクロ ;

*--- テストデータの作成 ;
data BPDATA ;
   input EXERCISE ID VISIT DBP SBP @@ ;
   if EXERCISE = 2 then VISIT2 = VISIT + 0.1 ;
                   else VISIT2 = VISIT ;
   label EXERCISE="Exercise" VISIT="Visit" VISIT2="Visit"
         DBP="Diastolic BP (mmHg)" SBP="Systolic BP (mmHg)" ;
cards;
1 1  0 124 164 1 7  0 117 167 1 13 0 105 155 1 19 0 115 167
1 1  1 120 157 1 7  1  79 138 1 13 1  99 129 1 19 1 106 130
1 1  2  98 135 1 7  2  96 134 1 13 2 118 152 1 19 2 107 136
1 1  3  95 137 1 7  3  98 114 1 13 3 122 137 1 19 3  51 144
1 2  0 130 150 1 8  0  90 144 1 14 0 102 148 1 20 0 113 147
1 2  1  98 140 1 8  1  89 130 1 14 1 101 143 1 20 1 108 129
1 2  2  86 166 1 8  2 103 137 1 14 2  65 166 1 20 2  97 109
1 2  3  93 134 1 8  3  96 157 1 14 3  95 134 1 20 3  93 152
1 3  0 131 159 1 9  0 123 161 1 15 0 111 134 1 21 0 101 170
1 3  1 101 144 1 9  1  78 127 1 15 1  98 158 1 21 1 110 133
1 3  2 108 131 1 9  2  94 176 1 15 2  84 134 1 21 2  95 170
1 3  3 120 135 1 9  3  95 112 1 15 3  97 155 1 21 3 107 144
1 4  0 100 140 1 10 0 121 145 1 16 0 116 174 1 22 0 114 173
1 4  1  86 169 1 10 1 121 127 1 16 1 103 155 1 22 1  94 134
1 4  2 107 145 1 10 2  93 142 1 16 2  79 131 1 22 2  99 105
1 4  3  88 133 1 10 3 111 114 1 16 3  96  87 1 22 3 125 127
1 5  0 102 156 1 11 0  96 185 1 17 0 122 179 1 23 0  98 157
1 5  1  82 132 1 11 1  85 163 1 17 1 122 174 1 23 1 105 145
1 5  2 112 148 1 11 2  92 125 1 17 2 109 175 1 23 2 104 118
1 5  3  99 177 1 11 3  80 131 1 17 3 105 146 1 23 3 117 163
1 6  0 122 189 1 12 0 107 139 1 18 0 120 159 1 24 0 120 154
1 6  1  92 105 1 12 1  95 190 1 18 1 125 167 1 24 1  86 130
1 6  2 102 172 1 12 2 112 156 1 18 2  92 121 1 24 2 104 131
1 6  3 120 120 1 12 3 112 111 1 18 3  99 180 1 24 3 122 167
2 25 0 108 160 2 31 0 133 190 2 37 0 104 161 2 43 0 120 152
2 25 1  96 163 2 31 1  95 149 2 37 1  90 145 2 43 1 102 134
2 25 2 113 144 2 31 2 102 143 2 37 2  99 173 2 43 2 112 141
2 25 3  92 134 2 31 3  82 151 2 37 3 120 155 2 43 3 113 121
2 26 0 101 170 2 32 0 116 126 2 38 0 106 175 2 44 0  94 161
2 26 1  81 163 2 32 1  98 190 2 38 1  99 170 2 44 1  80 146
2 26 2  94 135 2 32 2 109 155 2 38 2 127 140 2 44 2  98 148
2 26 3  94 158 2 32 3  95 133 2 38 3 107 191 2 44 3 104 145
2 27 0  99 176 2 33 0 114 165 2 39 0  96 175 2 45 0 119 148
2 27 1  81 186 2 33 1 121 130 2 39 1  86 151 2 45 1 108 144
2 27 2 116 150 2 33 2 108 149 2 39 2 103 132 2 45 2 115 160
2 27 3  98 145 2 33 3 111 125 2 39 3 113 112 2 45 3  95 150
2 28 0 108 133 2 34 0 104 140 2 40 0 124 150 2 46 0  92 178
2 28 1 125 136 2 34 1 128 135 2 40 1  95 154 2 46 1 100 158
2 28 2 110 154 2 34 2  85 122 2 40 2 108 147 2 46 2 111 152
2 28 3  87 157 2 34 3  95 174 2 40 3  88 146 2 46 3 102 160
2 29 0 120 175 2 35 0 111 162 2 41 0 115 134 2 47 0 117 176
2 29 1 102 162 2 35 1 101 107 2 41 1  78 132 2 47 1 113 148
2 29 2 100 145 2 35 2 126 175 2 41 2 102 123 2 47 2 128 141
2 29 3 111 165 2 35 3 121 171 2 41 3 103 181 2 47 3 119 122
2 30 0 108 143 2 36 0 124 179 2 42 0  95 171 2 48 0 118 170
2 30 1  92 154 2 36 1 120 150 2 42 1 143 157 2 48 1  87 143
2 30 2 102 127 2 36 2  95 173 2 42 2  96 158 2 48 2 113 144
2 30 3 115 128 2 36 3  94 122 2 42 3  94 154 2 48 3 115 146
;
run ;

*--- 平均値推移図作成マクロ ;
%macro G_MEAN(DATA=,GRP=,GRPF=,VAR=,X=,XF=,HIGE=both,SYMBOL=1) ;
   ods listing gpath="%sysfunc(pathname(work))" ;
   proc sgplot data=&DATA ;
      vline &X
      / response=&VAR group=&GRP stat=mean limitstat=stddev limits=&HIGE
        markers
        markerattrs=(symbol=%if       &SYMBOL = 1 %then circlefilled ;
                            %else %if &SYMBOL = 2 %then trianglefilled ;) ;
      xaxis type=linear ;
      format &GRP &GRPF.. &X &XF.. ;
   run ;
%mend G_MEAN ;

proc format ;
   value EXEF 1="Yes" 2="No" ;
   value VITF 0="Week 0" 1="Week 4" 2="Week 8" 3="Week 12" ;
run ;

%G_MEAN(DATA   = BPDATA,
        GRP    = EXERCISE,
        GRPF   = EXEF,
        VAR    = SBP,
        X      = VISIT2,
        XF     = VITF,
        HIGE   = both,
        SYMBOL = 2) ;

*--- 平均値推移図の2つの変数の重ね合わせ ;
%macro G_MEAN2(DATA=,GRP=,GRPF=,VAR=,VAR2=,YRANGE=,YRANGE2=,
               X=,XF=,HIGE=both,SYMBOL=1) ;
   ods listing gpath="%sysfunc(pathname(work))" ;
   proc sgplot data=&DATA ;
      vline &X
      / response=&VAR group=&GRP stat=mean limitstat=stddev limits=&HIGE
        markers
        markerattrs=(symbol=%if       &SYMBOL = 1 %then circlefilled ;
                            %else %if &SYMBOL = 2 %then trianglefilled ;) ;
      xaxis type=linear ;
      yaxis values=(&YRANGE) ;
      %if &VAR2 ne %str() %then %do ;
         vline &X
         / response=&VAR2 group=&GRP stat=mean limitstat=stddev limits=&HIGE
           markers y2axis
           markerattrs=(symbol=%if       &SYMBOL = 1 %then circlefilled ;
                               %else %if &SYMBOL = 2 %then trianglefilled ;) ;
         y2axis values=(&YRANGE2) ;
      %end ;
      format &GRP &GRPF.. &X &XF.. ;
   run ;
%mend G_MEAN2 ;

%G_MEAN2(DATA   = BPDATA,
        GRP     = EXERCISE,
        GRPF    = EXEF,
        VAR     = SBP,
        VAR2    = DBP,
        YRANGE  = %str(80 to 180 by 20),
        YRANGE2 = %str(80 to 180 by 20),
        X       = VISIT2,
        XF      = VITF,
        HIGE    = upper,
        SYMBOL  = 2) ;

*--- 複数グラフから選択してグラフを作成するマクロ ;
%macro G_MACRO(DATA=,ID=,GRAPH=,GRP=,GRPF=,VAR=,X=,XF=,HIGE=both,SYMBOL=1) ;
   ods listing gpath="%sysfunc(pathname(work))" ;
   %if &GRAPH = 1 %then %do ;       *--- 1. 個別推移図 ;
      proc sort data=&DATA ; by &ID &X ; run ;
      proc sgpanel data=&DATA noautolegend ;
         panelby &GRP / layout=columnlattice ;
         series x=&X y=&VAR / group=&ID lineattrs=(pattern=1 color=black) ;
         rowaxis integer ;
         format &GRP &GRPF.. &X &XF.. ;
      run ;
   %end ;
   %else %if &GRAPH = 2 %then %do ; *--- 2. 平均値推移図 ;
      proc sgplot data=&DATA ;
         vline &X
         / response=&VAR group=&GRP stat=mean limitstat=stddev limits=&HIGE
           markers
           markerattrs=(symbol=%if       &SYMBOL = 1 %then circlefilled ;
                               %else %if &SYMBOL = 2 %then trianglefilled ;) ;
         xaxis type=linear ;
         format &GRP &GRPF.. &X &XF.. ;
      run ;
   %end ;
   %else %if &GRAPH = 3 %then %do ; *--- 3. 棒グラフ ;
      proc sgpanel data=&DATA ;
         panelby &X / layout=columnlattice onepanel ;
         vbar &GRP  / response=&VAR group=&GRP
                      stat=mean ;
         format &GRP &GRPF.. &X &XF.. ;
      run ;
   %end ;
%mend G_MACRO ;

*--- 個別推移図 ;
%G_MACRO(DATA  = BPDATA,
         ID    = ID,
         GRAPH = 1,
         GRP   = EXERCISE,
         GRPF  = EXEF,
         VAR   = SBP,
         X     = VISIT,
         XF    = VITF) ;

*--- 平均値推移図 ;
%G_MACRO(DATA   = BPDATA,
         GRAPH  = 2,
         GRP    = EXERCISE,
         GRPF   = EXEF,
         VAR    = SBP,
         X      = VISIT2,
         XF     = VITF,
         HIGE   = upper,
         SYMBOL = 1) ;

*--- 棒グラフ ;
%G_MACRO(DATA   = BPDATA,
         GRAPH  = 3,
         GRP    = EXERCISE,
         GRPF   = EXEF,
         VAR    = DBP,
         X      = VISIT,
         XF     = VITF) ;



*** 6章演習問題 ;

*--- 1) ;
options mprint mlogic symbolgen ;
%macro CALCSUM(DATA=,VAR=,ODS=,SUM=) ;
   ods %if &ODS = 1 %then rtf ;
                    %else pdf ;;
   proc tabulate data=&DATA ;
      var &VAR ;
      table &VAR.*(&SUM) ;
   run ;
   ods %if &ODS = 1 %then rtf ;
                    %else pdf ; close ;
%mend CALCSUM ;

*--- 2) ;
%CALCSUM(DATA=sashelp.cars,VAR=MPG_CITY,ODS=2,SUM=n mean stddev min median max) ;