SAS

layoutステートメントを使いこなす(2) Multi-cell layout

single cell layoutブロックは1つのグラフエリアを配置するレイアウトであるのに対し、Multicell layoutは複数のグラフエリアを配置するレイアウトです。

Multicell layout

Multi-cell layoutにはGRIDDEDレイアウトとLATTICEレイアウトの2種類があります。

GRIDDEDレイアウト

複数のグラフをそのまま格子状に配置する最もシンプルなレイアウトです。各区画は完全に独立しているため、それぞれの区画の体裁を定義する必要があります。

以下のコードはGRIDDEDレイアウトで4つの区画を定義し、同じデータ(sashelp.iris)を表示させています。entryステートメントで各区画の番号を表示させています。

proc template;
define statgraph grid;
begingraph;
   layout gridded / rows=2 columns=2;
      layout overlay;
         scatterplot x=SepalLength y=SepalWidth;
         entry "No.1" /autoalign=auto textattrs=(size=24);
      endlayout;

      layout overlay;
         scatterplot x=SepalLength y=SepalWidth;
         entry "No.2"/autoalign=auto textattrs=(size=24);
      endlayout;

      layout overlay;
         scatterplot x=SepalLength y=SepalWidth;
         entry "No.3"/autoalign=auto textattrs=(size=24);
      endlayout;
 
      layout overlay;
         scatterplot x=SepalLength y=SepalWidth;
         entry "No.4"/autoalign=auto textattrs=(size=24);
      endlayout;
   endlayout;
endgraph;
end;
run;

proc sgrender data=ds1 template=grid;
run;
実行結果

 

GRIDDEDレイアウトはグラフの中に表を挿入するのに適したレイアウトで、sgplotのinsetステートメントと同様のことができます。

以下の例では散布図の中にのテーブルを挿入し、回帰直線の傾き、切片およびR2の値を表示しています。

ただしこの方法だとテーブルの値はデータセットの変数は指定できません。なのでマクロ変数かdynamic variableを使って文字列を代入するしかないですね。大きな表を挿入するときは表示方法を再考したほうが良いかもしれません。axistableを使うのも手かも。

proc reg data=sashelp.iris noprint outest=REG edf;
   model SepalWidth=SepalLength / adjrsq;
run;

data _NULL_;
   set reg; 
   call symputx("INT", put(round(Intercept,0.01),8.2));
   call symputx("SLOPE", put(round(SepalLength,0.01),8.2));
   call symputx("RSQ", put(round(_RSQ_,0.0001),8.4));
run;

proc template;
define statgraph grid;
dynamic _SLOPE _INT _RSQ;
begingraph;
   layout overlayequated /
          equatetype=squaredata;
      layout gridded / autoalign=(TOPLEFT TOPRIGHT) columns=2 border=true;
         entry halign=left "Slope" / ;
         entry halign=right _SLOPE /pad=(left=10);
         entry halign=left "Intercept";
         entry halign=right _INT /pad=(left=10);
         entry halign=left "R square";
         entry halign=right _RSQ /pad=(left=10);
      endlayout;
      scatterplot x=Sepallength y=SepalWidth;
      lineparm x=0 y=_INT slope=_SLOPE / clip=true lineattrs=(color=red);
  endlayout;
endgraph;
end;
run;

proc sgrender data=sashelp.iris template=grid;
   dynamic _SLOPE=&SLOPE. 
           _INT=&INT. 
           _RSQ=&RSQ.;
run;

実行結果

LATTICEレイアウト

LATTICEレイアウトはよりGRIDDEDレイアウトよりも多機能なレイアウトです。

GRIDDEDレイアウトはすべての軸は独立していましたが、LATTICEレイアウトはcolumn axesおよびrow axesを設置することで軸を各区画で共有するすることができます。またCELLブロックとSIDEBARブロックを利用することで各区画にヘッダーを設置したりプロットエリアの外側に凡例などを設置できます。

CELLブロックは格子の1区画を定義します。、各cellにはcellheaderブロックを利用することによりヘッダーを表示することができます。CELLブロックを必要な数設置し、CELLブロックの中にOVERLAYやREGIONレイアウトを設置してグラフを定義します。

GRIDDEDレイアウト同様に同じIrisのデータを4つ配置してみます。

proc template;
define statgraph lattice;
begingraph;
layout lattice / rows=2 columns=2;
   cell;
   cellheader; 
      entry "No.1" / textattrs=(size=14);
   endcellheader;
   layout overlay / 
      xaxisopts=(griddisplay=on)
      yaxisopts=(griddisplay=on);
      scatterplot x=SepalLength y=SepalWidth;
   endlayout;
   endcell;

   cell;
   cellheader;
      entry "No.2" / textattrs=(size=14);
   endcellheader;
   layout overlay /
      xaxisopts=(griddisplay=on)
      yaxisopts=(griddisplay=on);
      scatterplot x=SepalLength y=SepalWidth;
   endlayout;
   endcell;

   cell;
   cellheader;
      entry "No.3" / textattrs=(size=14);
   endcellheader;
   layout overlay /
      xaxisopts=(griddisplay=on)
      yaxisopts=(griddisplay=on);
      scatterplot x=SepalLength y=SepalWidth;
   endlayout;
   endcell;

   cell;
   cellheader;
      entry "No.4" / textattrs=(size=14);
   endcellheader;

   layout overlay / 
      xaxisopts=(griddisplay=on)
      yaxisopts=(griddisplay=on);
      scatterplot x=SepalLength y=SepalWidth;
   endlayout;
   endcell;
 
   sidebar;
      entry "Sidebar Area" / textattrs=(size=16);
   endsidebar;
endlayout;
endgraph;
end;
run;

実行結果

軸がそれぞれ独立して設置されています。共通の軸を設置するには以下のようにします。

proc template; 
define statgraph lattice;
begingraph;
layout lattice / rows=2 columns=2 columndatarange=union rowdatarange=union columngutter=5 rowgutter=5; 

columnaxes; 
columnaxis / display=(ticks tickvalues) griddisplay=on;
columnaxis / display=(ticks tickvalues) griddisplay=on;
endcolumnaxes;

rowaxes;
rowaxis / display=(ticks tickvalues) griddisplay=on;
rowaxis / display=(ticks tickvalues) griddisplay=on;
endrowaxes;

/*cell 1*/
cell;
cellheader;
entry "No.1" / textattrs=(size=14);
endcellheader;

layout overlay;
scatterplot x=SepalLength y=SepalWidth;
endlayout;
 endcell;

/*cell 2*/
cell;
cellheader;
entry "No.2" / textattrs=(size=14);
endcellheader;

layout overlay / xaxisopts=(griddisplay=on)
yaxisopts=(griddisplay=on);
scatterplot x=SepalLength y=SepalWidth;
endlayout; 
endcell;

/*cell 3*/
cell;
cellheader;
entry "No.3" / textattrs=(size=14);
endcellheader;

layout overlay;
scatterplot x=SepalLength y=SepalWidth;
endlayout;
endcell;

/*cell 4*/
cell;
cellheader;
entry "No.4" / textattrs=(size=14);
endcellheader;

layout overlay;
scatterplot x=SepalLength y=SepalWidth;
endlayout;
endcell;

sidebar / align=bottom;
entry "Sepal Length" / textattrs=(size=14);
endsidebar;

sidebar / align=left;
entry "Sepal Width" / rotate=90 textattrs=(size=14);
endsidebar;
endlayout;
endgraph;
end;
run;

各区画の軸が同じものであれば、行と列に共通軸を設置できます。

columnaxesとrowaxesブロックで行と列の軸を定義します。この時行と列の数だけrowaxisステートメントおよびcolumnaxisステートメントを追加し軸の設定を行います。今回は目盛のみ表示しグリッドを表示させています。

なおsidebarはalignオプションで上下左右に設置可能です。

実行結果

まとめ

GRIDDEDレイアウトおよびLATTICEレイアウトはどちらも複数の独立したグラフを格子状に設置できます。

単純に複数のグラフを並べたいだけであればGRIDDEDレイアウトを使用したほうがコードが少なくなります。
またグラフ内部にテーブルを設置したい場合はOVERLAYレイアウトの内部にGRIDDEDレイアウトを設置することで実現できます。

行と列に共通軸を設置したい場合やヘッダーを設置したい場合はLATTICEレイアウトを利用したほうが良いでしょう。