ラベル proc template の投稿を表示しています。 すべての投稿を表示
ラベル proc template の投稿を表示しています。 すべての投稿を表示

proc corrのアウトプットで、相関係数の値やp値の値に基づいて色を変える方法

最近交流させていただいております方から、「膨大な数の変数の相関をみる場合があるのですが、相関係数の値が一定以上、P値の値が一定以下の際に、そこがわかるようにアウトプットに色づけしたい」といった趣旨の質問がありました。

プロシジャのアウトプットをダイレクトにいじるのは、あんまやったことないから無理です~!って逃げるところでしたが、ちょっと頑張ってみました。

確かにproc corrかけると、対象変数の相関行列がでてくるんですが、変数多いと、目が滑って見落としちゃうことあります。

まず

data Q1;
 A=2;B=1;C=2;D=3;E=9;F=9;output;
 A=4;B=2;C=3;D=8;E=2;F=22;output;
 A=6;B=1;C=3;D=2;E=13;F=9;output;
 A=8;B=4;C=6;D=3;E=23;F=1;output;
 A=10;B=5;C=7;D=5;E=8;F=8;output;
run;

適当にデータを作ります。

で、

ods trace on;
proc corr data=Q1;
run;
ods trace off;

とすると










































と、いっぱい出てきます。

今回、いじくりたいのは3つめの相関行列の表です。

ods traceつけて実行したので、ログには各アウトプットの情報がでています。
そこから相関行列に該当するものを探します。
(ods tarce onについて詳しくは




みっけ! そこで、テンプレートの箇所をみます。
このテンプレートこそが、解析結果をアウトプットするためのデザイン情報、スタイルシートみたいなもんなんですね。

そこで、テンプレートを特定したら、次にそのテンプレートの中身を展開して確認します

proc template;
 source Base.Corr.StackedMatrix;
run;

templateプロシジャでsourceの後に、確認したい先ほどのテンプレート名を指定して実行
ログに以下のようなものがでてきます。






















ふむふむ、成程。さっぱりわからん。読めるか、こんなもん。
まあ、GraphTemplateLangage(GTL)やってる方なら知っているかもしれませんが、これはグラフじゃない方ののテンプレートランゲージなんですね。

これをカスタマイズするのか~。まあ頑張って読んでみます。
大切なのは、どこの記述が、アウトプットのどこに紐づいているかを見極めることです。

じっくり見てると、なんとな~く
column (RowName RowLabel) (Matrix) * (Matrix2) * (Matrix3) * (Matrix4);
の箇所が、全体の構造に関係してる気がしませんか?勘で。

さっきのアウトプットと見比べてみると、column(RowName RowLabel)はどうも、縦にA B C D E  F、横にA B C D E Fとなっている、アウトプットの一番外側の部分ではないか?と当たりがつきます(強引)。そうすると、次に(Matrix)とあるものは、もしかして相関係数の行列に対応しているのでは?と推測されます(強引)、じゃあ次の(Matrix2)はP値か!
じゃあ(Matrix3)と(Matrix4)はなんなんだ? あ、そうか、corrプロシジャにはたくさんオプションが付けられる!その指定によっては出現する階層じゃないのか!(もはや、こじつけ)

ということがわかります。まあ、詳しくはods関係をじっくり勉強してください。

そして、もう一つさっきのTemplateプロシジャの出力で重要ななのが、NOTEの部分で、このcorrプロシジャの相関行列をだすテンプレートはSASHELPのTMPLISTって中に格納されているよって部分です。このことを心に留めていてください。


さて、実際にこっからテンプレート改造手術を開始する前に下準備

proc format;
 /*相関係数の色*/
   value rf low--0.7='RED'
            -0.7<--0.4='BLUE'
            -0.4<--0.2 ='GREEN'
            -0.2-<0.2='WHITE'
            0.2-<0.4='GREEN'
            0.4-<0.7='BLUE'
            0.7-<1='RED'
            1='WHITE';
  /*P値の色*/
   value pf low-0.01='RED'
            0.01<-0.05='BLUE'
            0.05<-high='BLACK';
run;

まあそのまんまですね、相関係数の値によって変わるフォーマット、P値によって変わるフォーマットを先んじて作っておきます。

そしたら

proc template;
   edit Base.Corr.StackedMatrix;
      column (RowName RowLabel) (Matrix) * (Matrix2);
      edit matrix;
         cellstyle _val_ as {backgroundcolor=rf.};
       end;
        edit matrix2;
          style={foreground=pf.};
       end;
      end;
run;

これで手術完了です。
 edit Base.Corr.StackedMatrix;は、カスタマイズする元のテンプレート名を指定
column (RowName RowLabel) (Matrix) * (Matrix2);
は、今回はここまでの定義以上は必要ないので、こうしてます
edit matrix;からend;までが、相関係数の部分をいじりますよって意味です。
cellstyle _val_ as {backgroundcolor=rf.}; これはセルの値に基づいて、セルのスタイルを変更してください、背景色はrfフォーマットで定義しますって意味です。
edit matrix2;からも同様で、今度はセル全体ではなく、値の書式のみを変更する書き方です。

そして実行すると、このテンプレートはWORK.templateというところに保存されます。え?SASHELPじゃないの?って思うかもしれませんが、SASHELPのテンプレートをうっかり変な風に変えちゃったら、今後のcorrプロシジャのアウトプット全部変になって大変でしょう?
だからWORKに複製が作られて、そこが改造されるようになってるんです。

で

ods path work.template(update) sashelp.tmplmst;
ods html file='/folders/myfolders/sample.html';
proc corr data=Q1;
 ods select PearsonCorr;
run;
ods html close;

です。あ、ちなみにfile=の記述は、なぜかUniversityではこれでhtmlつくらないと、僕の環境でうまくいかなかったのでつけてるだけで、本来いらないです。
リスト出力以外ならods pdf;でもods rtf;でもods htmlでもなんでもいいです。

ods path work.template(update) sashelp.tmplmst;
これは、WORKにある、カスタマイズしたテンプレートがあるかを先に見ろよ、あったらそっち使えよ!って命令です。

結果は






















です。相関係数の絶対値が0.7以上ならセルが赤、0.4以上なら青、0.2以上は緑になります。
P値は5%以下なら青字、さらに1%以下なら赤字になります。

カスタマイズしたテンプレートを消す場合
proc template; 
   delete base.corr.stackedmatrix;
run;

でOKです。

symbolimageでグラフのシンボルに好きな画像を使う方法。例えば散布図で将棋盤を表現

SAS9.4から、SG系グラフでsymbolimageを使うことができ、プロットのシンボルを自由な画像にすることができます。

印象としては、実装遅くない?って感じですよね。結構大事な機能だと思うので9.2から入れりゃいいのに、、。


で、今回はGTL&SGRENDERで散布図書きます。
で、どうせなら、散布図の概念に捉われない使い方をしたいと思います。

今、以下のようなデータセットがあったとします。

data Q1;
X=1;Y=9;KOMA='▲香車';output;
X=2;Y=9;KOMA='▲桂馬';output;
X=3;Y=9;KOMA='▲銀将';output;
X=4;Y=9;KOMA='▲金将';output;
X=5;Y=9;KOMA='▲王将';output;
X=6;Y=9;KOMA='▲金将';output;
X=7;Y=9;KOMA='▲銀将';output;
X=8;Y=9;KOMA='▲桂馬';output;
X=9;Y=9;KOMA='▲香車';output;
X=2;Y=8;KOMA='▲飛車';output;
X=8;Y=8;KOMA='▲角行';output;
X=1;Y=7;KOMA='▲歩兵';output;
X=2;Y=7;KOMA='▲歩兵';output;
X=3;Y=7;KOMA='▲歩兵';output;
X=4;Y=7;KOMA='▲歩兵';output;
X=5;Y=7;KOMA='▲歩兵';output;
X=6;Y=7;KOMA='▲歩兵';output;
X=7;Y=7;KOMA='▲歩兵';output;
X=8;Y=7;KOMA='▲歩兵';output;
X=9;Y=7;KOMA='▲歩兵';output;
X=1;Y=1;KOMA='△香車';output;
X=2;Y=1;KOMA='△桂馬';output;
X=3;Y=1;KOMA='△銀将';output;
X=4;Y=1;KOMA='△金将';output;
X=5;Y=1;KOMA='△王将';output;
X=6;Y=1;KOMA='△金将';output;
X=7;Y=1;KOMA='△銀将';output;
X=8;Y=1;KOMA='△桂馬';output;
X=9;Y=1;KOMA='△香車';output;
X=8;Y=2;KOMA='△飛車';output;
X=2;Y=2;KOMA='△角行';output;
X=1;Y=3;KOMA='△歩兵';output;
X=2;Y=3;KOMA='△歩兵';output;
X=3;Y=3;KOMA='△歩兵';output;
X=4;Y=3;KOMA='△歩兵';output;
X=5;Y=3;KOMA='△歩兵';output;
X=6;Y=3;KOMA='△歩兵';output;
X=7;Y=3;KOMA='△歩兵';output;
X=8;Y=3;KOMA='△歩兵';output;
X=9;Y=3;KOMA='△歩兵';output;
run;

ちなみに▲は先手を表し、△は後手を表す将棋の符号です。

で、任意のフォルダに、フリー素材画像のサイトから駒の画像をとってきて保存します。
先手と後手で画像の向きがひっくり返りますが、ここは単純に反転した画像を用意して使います。
(使用したサイト:http://sozai.7gates.net/docs/japanese-chess/)























でコードは

ods path(prepend) work.templat(update);
proc template;
 define statgraph syogi;
 begingraph;
 symbolimage name=S_OU image='/folders/myfolders/koma/▲王将.png';
 symbolimage name=S_HISYA image='/folders/myfolders/koma/▲飛車.png';
 symbolimage name=S_KAKU image='/folders/myfolders/koma/▲角行.png';
 symbolimage name=S_KINN image='/folders/myfolders/koma/▲金将.png';
 symbolimage name=S_GINN image='/folders/myfolders/koma/▲銀将.png';
 symbolimage name=S_KYOUSYA image='/folders/myfolders/koma/▲香車.png';
 symbolimage name=S_KEIMA image='/folders/myfolders/koma/▲桂馬.png';
 symbolimage name=S_HU image='/folders/myfolders/koma/▲歩兵.png';
 symbolimage name=G_OU image='/folders/myfolders/koma/△王将.png';
 symbolimage name=G_HISYA image='/folders/myfolders/koma/△飛車.png';
 symbolimage name=G_KAKU image='/folders/myfolders/koma/△角行.png';
 symbolimage name=G_KINN image='/folders/myfolders/koma/△金将.png';
 symbolimage name=G_GINN image='/folders/myfolders/koma/△銀将.png';
 symbolimage name=G_KYOUSYA image='/folders/myfolders/koma/△香車.png';
 symbolimage name=G_KEIMA image='/folders/myfolders/koma/△桂馬.png';
 symbolimage name=G_HU image='/folders/myfolders/koma/△歩兵.png';

 discreteattrmap name='kifmap';
   value '▲王将' / markerattrs=(symbol=S_OU);
   value '▲飛車' / markerattrs=(symbol=S_HISYA);
   value '▲角行' / markerattrs=(symbol=S_KAKU);
   value '▲金将' / markerattrs=(symbol=S_KINN);
   value '▲銀将' / markerattrs=(symbol=S_GINN);
   value '▲香車' / markerattrs=(symbol=S_KYOUSYA);
   value '▲桂馬' / markerattrs=(symbol=S_KEIMA);
   value '▲歩兵' / markerattrs=(symbol=S_HU);
   value '△王将' / markerattrs=(symbol=G_OU);
   value '△飛車' / markerattrs=(symbol=G_HISYA);
   value '△角行' / markerattrs=(symbol=G_KAKU);
   value '△金将' / markerattrs=(symbol=G_KINN);
   value '△銀将' / markerattrs=(symbol=G_GINN);
   value '△香車' / markerattrs=(symbol=G_KYOUSYA);
   value '△桂馬' / markerattrs=(symbol=G_KEIMA);
   value '△歩兵' / markerattrs=(symbol=G_HU);
 enddiscreteattrmap;
 discreteattrvar attrvar=KOMAC var=KOMA attrmap='kifmap';

 layout overlay /yaxisopts=(reverse=true griddisplay=ON
                            linearopts=(tickvaluesequence=(start=1 end=9 increment=1)))
                 xaxisopts=(reverse=true  griddisplay=ON
                            linearopts=(tickvaluesequence=(start=1 end=9 increment=1)));
    scatterplot x=X y=Y /group=KOMAC markerattrs=(size=25pt);
 endlayout;
 endgraph;
 end;

proc sgrender template=syogi data=Q1;
run;

結果は

































てな、感じです。まだマス目がうまく表現できてないので、今後の課題ですね。

最後に「新手一生」を掲げられた升田幸三の言葉を2つほど

『文化なんてしょせん無駄なもんなんだ。でもその明かりが、届く範囲の人に何かをもらたしている。将棋も同じじゃないか』

『若い頃、全く生産性のない「将棋指し」という職業に寂莫とした思いをしたことがあります。国家に、国民に、いかほどの貢献をしているだろうかと。でも、文化というものはムダから発展していくのだ、ということを会得してからは「将棋指し」に打ち込めるようになりました。』



実績値と予測値とかの棒グラフをGTLで作る

以前、[GKPIプロシジャは見た目が楽しくて良いという話]
http://sas-tumesas.blogspot.jp/2014/09/gkpi.html

で、達成度と目標値みたいなプロットをあげました。遊び的な話題として書いたのですが、意外と受けたみたいで、売り上げと予測値の月毎の棒グラフにしたいが、どう書くかみたいなメールをいただいたりしました。

基本的にユーザーの要求に応じて、自由なグラフを書くなら、僕はもう基本的にはGTLを勉強して使うべきだと思います。つまりproc templateでグラフテンプレートを定義して、proc sgrenderでそれを適用するということです。

GTLは9.2では、まだ出はじめということで実際使用していて表現力が足りないなと感じる部分がありますが、9.3以降はannotateも使えますし、きちんとコードを書きさいすれば、基本的に思った通りのものを大体実現できると言っていいでしょう。

GTLは覚えるのは、かなり時間がかかりますが、GTLさえ覚えてしまえば、乱暴な話、sgplotとかsgscatterとかそれぞれのグラフを書くプロシジャなんて全く覚える必要なく、全部GTLでかけます。

内部的には全てGTLで動いてるから当たり前といえば当たり前で、根源的な存在なので、それさえ押さえとけば無敵です。
(ただ、さすがにgkpiプロシジャのスピードメーター表示みたいな特殊なものはGTLでも厳しいかも)

偉そうなこと言いつつ、僕はまだまだ全然ですが。
いつかきちんと勉強して1から解説します(そんなこと言ってばっかですけど)

data Q1;
TIME=1;ACTUAL=100;PREDICT=80;output;
TIME=2;ACTUAL=90;PREDICT=100;output;
TIME=3;ACTUAL=120;PREDICT=100;output;
TIME=4;ACTUAL=120;PREDICT=120;output;
TIME=5;ACTUAL=100;PREDICT=80;output;
run;








TIMEが月とか、日とか、要はX軸にもってくるやつで、ACTUALが実績値で、PREDICTが予測値とか目標値だとして

proc template;
 define statgraph G1;
 begingraph;
 layout overlay;
  barchart X=TIME Y=ACTUAL/target=PREDICT;
 endlayout;
 endgraph;
 end;
run;

proc sgrender data=Q1 template=G1;
run;

ポイントはtarget=です。

で結果は





















こんな感じですね。

提示したのは必要最低限のパターンなので、ここから色つけたり、様々な飾りつけは、GTLを勉強して頑張ってみてください。




ODS Graphics Editorの話 (特別なライセンスなし、SAS/GRAPHでできる便利な機能)

templateプロシジャで、Glaph Template Languageで、グラフのテンプレートを作って、proc sgrenderでそのテンプレートを指定して、プロットする。

SAS9.2以降、SG系グラフの登場により、グラフの表現力はケタ違いにアップしましたが、その代わり、最初のハードルも随分高くなってしまった気がします。

いきなりGTLガリガリ書いてグラフを作るのは、ちょっと難しいので、最初のうちは
SASのグラフサンプル集http://support.sas.com/sassamples/graphgallery/PROC_SGRENDER.html

やSASユーザー総会で公開されているものや、或いは書籍、コピペして、少しずつカスタマイズして
自分のものにしていくのがいいと思います。
リンクさせていただいている「僕の頁 <SASと臨床試験と雑談と>」(http://sasboku.blog.fc2.com/)
にもGTLを使ったプロットが公開されていて勉強になります。

で、今回紹介するのは、それとは違ったアプローチです。
GUI、ようはプログラムを書かずに手でグラフを書いて、それを自動的にコード化する話です。

まず、適当なデータをつくります。

data TEST;
call streaminit(2014);
do GROUP='A','B';
 do i=1 to 100;
  x=rand('uniform');
  y=rand('uniform');
  output;
 end;
end;
drop i;
run;


そしたら、まず、SASをインストールする時に、ODS Graphics Editerにチェックをつけた人は、すでにアイコンがあるか、すべてのプログラムから立ち上げられるので、そうしてください。





もし、そういったものが見当たらない人は

%sgdesign;

とエディタに書いて、実行してください。
何かが裏で凄い動いた感じがして、10数秒後、

















こんな画面がでてきます。

ここで、いろんな形のグラフを選ぶことで、実は相当高度なグラフもかけます。
















試しにグラフギャラリーから「グループ化散布図」でも選んでみましょう









グラフを選ぶと、次はグラフに使うデータセットを指定します。
デフォルトがなぜかSASHELPなので、参照元にするライブラリを指定します。


※ちなみにここで、%sgdesign;で起動した人は、WORKの中をみてみましょう。
わけわかんないデータセットであふれているはずですが、これは、グラフを書くサンプル用の
データセットを勝手に用意してくれいるんです。迷惑です。
















で、最初につくったデータセットを指定します


そしたら























X軸に対応する変数とY軸に対応する変数、そしてグループ化する変数をプルダウンで
選びます。

そしたら、それだけで、グラフがポンとでてきます。
で、なんと、そのグラフを手で修正できます。

まずはグラフタイトルをクリックして、好きなタイトルにします



















右クリックで、軸や背景などのいろんなプロパティをいじれます。
感覚的にはEXCELのグラフを編集するのと全く同じです。

背景色を灰色にしてみました。



















要素の追加で、さらにプロットを重ねたり
フリーテキストや凡例などを追加できます



















凡例を追加してみました























やりたい放題やって、気がすんだら、ここからが本番













表示から「コード」をクリックすると





なんと、proc templateでのテンプレート定義から
proc sgrenderの実行までを全てコード化してくれます。


プロットに指定した変数はdynamicステートメントで受け渡すことを想定したコード化を
してくれるので、標準化もしやすく、超便利。

あとはこれをエディタにペタ

proc template;
define statgraph sgdesign;
dynamic _X _Y _GROUP;
begingraph / backgroundcolor=CXE8E6E8;
entrytitle _id='title' halign=center '散布図ですわ' /;
entryfootnote _id='footnote' halign=left 'Type in your footnote...' /;
layout lattice _id='lattice' / columndatarange=data columngutter=10 rowdatarange=data rowgutter=10;
         layout overlay _id='overlay' / xaxisopts=(gridDisplay=on label='X軸のラベルも自由') yaxisopts=(linearopts=(viewmin=0.2 viewmax=0.9 ) tickvalueattrs=(size=12) gridDisplay=on type=linear);
            scatterplot _id='scatter' x=_X y=_Y / group=_GROUP name='scatter';
            discretelegend _id='legend' 'scatter'  / border=true displayclipped=true down=1 halign=center location=inside opaque=false order=columnmajor valign=top;
         endlayout;
endlayout;
endgraph;
end;
run;

proc sgrender data=WORK.TEST template=sgdesign;
dynamic _X="X" _Y="Y" _GROUP="GROUP";
run;

で実行するだけで

さっきまで、手でいじって作ってたグラフが、ポンです。

















これは、GTLを勉強するとき、何と何が結びついているかを理解する上でも、大変役立ちますね。
レイアウト分割の複合グラフを、一からコードで起こすのは、まあ、なかなか、つらいですよね、それはそれで勉強になるけども