2015年7月31日金曜日

RWIで集計表を作る



今回のゴールはRWIで以下の表をPDF形式で作成することです。
集計に使うデータセットは「SASHELP.CARS」の先頭80obsとします。

注意:
SAS9.4以降で動作します。
また、今回のプログラムには、HTML形式でサポートされていないオプションを使用しています。




ステップ①

  • まずFREQプロシジャで集計し、結果をデータセットに出力します。
  • 結果のデータセットを加工して、RWIで出力しやすい形にします。

*=== 集計 ===========================================;
proc freq data=SASHELP.CARS (obs=80) noprint;
     tables MAKE / out=OUT1;
     tables TYPE / out=OUT2;
run;

*=== 集計結果を出力の形に加工 =======================;
data OUT;
     length NO 8. ITEM1 ITEM2 COL1 COL2 $20.;

     set OUT1 (in=_IN1)
           OUT2 (in=_IN2)
     ;
     *** 項目No.、項目名の導出 ******************;
     NO    = whichn(1,of _IN:);
     ITEM1 = choosec(NO, "Make","Type");
     ITEM2 = coalescec(MAKE,TYPE);

     *** Nとパーセントを出力の形に **************;
     COL1 = cats(COUNT);
     COL2 = cats( "(", put(round(PERCENT,.1), 8.1) ,")" );
run;






ステップ②

  • 上で作ったデータセットをRWIで出力します。

*=== 出力開始 ===========================================;
options nodate;
ods pdf file="出力するファイルのパス\RWI_Sample2.pdf" style = printer;

data _NULL_;
     length LINE $5.;

     set OUT end=EOF;
     by NO ;

     if _N_=1 then do;
         dcl odsout ob();
         ob.title(data:'集計結果');
         ob.table_start();

         *** 項目名を出力 *************************;
         LINE = "LR";
         ob.head_start();
         ob.row_start();
             ob.format_cell(data:"因子", inhibit:LINE, style_attr:"background=white cellwidth=3cm just=l");
             ob.format_cell(data:""       , inhibit:LINE, style_attr:"background=white cellwidth=3cm just=l");
             ob.format_cell(data:"n"     , inhibit:LINE, style_attr:"background=white cellwidth=2cm just=r");
             ob.format_cell(data:"(%)"  , inhibit:LINE, style_attr:"background=white cellwidth=2cm just=l");
         ob.row_end();
         ob.head_end();
     
end;

     *** データの中身を出力 ***********************;
     * 各集計項目の先頭を1行あける。 ;
     if first.NO then do;
         ob.row_start();
         ob.format_cell( data:ITEM1 , inhibit:"BLR", column_span:4, style_attr:"just=l");
         ob.row_end();
     end;

     * データの中身を出力 ;
     * 変数LINEに、行毎の罫線の設定を格納 ;
     LINE = "TBLR";
     if EOF then LINE="TLR";

     ob.row_start();
         ob.format_cell( data:""        , inhibit:LINE, style_attr:"just=l");
         ob.format_cell( data:ITEM2 , inhibit:LINE, style_attr:"just=l");
         ob.format_cell( data:COL1  , inhibit:LINE, style_attr:"just=r");
         ob.format_cell( data:COL2  , inhibit:LINE, style_attr:"just=l");
     ob.row_end();

     * 最後に表作成を終了 ;
     if EOF then ob.table_end();
run;

ods pdf close;


出力結果

※ プログラム中の青字のパスを各時環境のパスに変更してください。



今回のポイントは format_cellメソッド内の「inhibitオプション」による罫線の細かい指定です。

構文
FORMAT_CELL( INHIBIT:'罫線を非表示にする位置 ' )

罫線を非表示にする位置
T ・・・ 上側
B ・・・ 下側
L ・・・ 左側
R ・・・ 右側

例 : 上下の罫線を非表示にする
FORMAT_CELL( INHIBIT : 'TB' ) ;

注意:現状、inhibitオプションはHTML形式ではサポートされていない


RWIについては、以下の入門シリーズにまとめています。
レポート作成インターフェイス(RWI)入門1


📝注意

記事の中で使用している「_N_」「END=オプション」「FIRST.BY変数」は「サブセット化IF」と一緒に使用すると正しく動かなくなりやすいです。


割り当てられたライブラリまたはファイル参照をログに出力する。


以下のプログラムで、全ての参照名と参照パスがログに出力されます。


ライブラリの確認
  libname _all_  list;



ファイル参照の確認
  filename _all_  list;



システム用の参照も出てきます。

2015年7月30日木曜日

集計結果をデータセット化する場合、MEANSよりSUMAMYプロシジャの方が効率的



サンプル作成

data DT1;
input A B @@;
cards;
3 10  2 20  1 30
;



SUMMARYプロシジャでAの平均値とBの平均値を求めてデータセットに出力したいとします。
これはOUTPUTステートメントに以下の書き方をするだけでokです。

proc summary data=DT1;
   output out=OUT1  mean(A)=A_MEAN  mean(B)=B_MEAN;
run;



構文

OUTPUT OUT=出力データセット名  統計量( 対象変数 ) = 出力変数名 ・・・;



MEANSプロシジャでも同じ書き方が出来るけど、、

proc means data=DT1 noprint;
   output out=OUT1  mean(A)=A_MEAN  mean(B)=B_MEAN;
run;


MEANS vs SUMMARYプロシジャ」で解説した通り、

MEANSプロシジャでは「VARステートメントを省略すると、CLASSステートメント等のその他のステートメントに指定していない全ての数値変数」が裏で集計されているようで、

SUMMARYプロシジャの方が、余計な集計が行われないし、短い文で書けるので効率的です。


TITLEまたはFOOTNOTEを全てクリアする


以前、以下のようなプログラムを見かけました。

* サンプルデータ作成 ;
data a;
   A=1;
run;

* 出力 ;
title "aa";
title2 "bb";
title3 "cc";

proc print; run;

title;
title2;
title3;





タイトルをクリアするために
title;
title2;
title3;
と書いていますが、これは以下のプログラムでまとめてクリアできます。
goptions reset=title;
もしくは
title;

footnoteの場合は、以下のように書けます。
goptions reset=footnote;
もしくは
footnote;


SAS入門


SASを使い始める時に覚えておくとよさそうな記事をまとめました。
順次追加予定。


基礎



実践


集計

PUT vs PUTLOG


両方ともログに文字を出力するステートメントです。

data _NULL_;
   put "aaa";
   putlog "bbb";
run;


ログ
aaa
bbb


同じ機能なら、PUTLOG 要らないじゃんってなりますが、
FILEス テートメントがあると PUT は外部ファイルへの出力に切り替わります。
一方 PUTLOG は変わらずログへの出力のままです。

data _NULL_;
   file "C:\TEST1.txt";
   put "aaa";
   putlog "bbb";
run;


TEST1.txt
aaa

ログ
bbb


上の例のように外部ファイルとログへの出力を同時進行で行いたい場合に使い分けられるわけです。

算術演算子による足し算とSUM関数の違い


SAS覚えはじめの頃に知っておくと便利な違い。

サンプルデータ作成
data DT1;
   A=1;
   B=2;
   C=.;
run;

 A  
 B  
 C  
 1 
 2 
 .


算術演算子とSUM関数の違い
data DT2;
   set DT1;

   * 算術演算子による足し算 ;
   X1=A+B+C;

   * SUM関数 ;
   X2=sum(A,B,C);
run;

 A  
 B  
 C  
 X1 
 X2 
 1 
 2 
 .
 .
 3

算術演算子の場合、足す変数にひとつでも欠損値があると、足し算の結果は欠損値になります。
一方SUM関数の場合、欠損値以外の値を合計した値を返してくれます。