SAS

GTLでフォレストプロットを作成する (3)行にカラーバンドを配置する

フォレストプロットは色々作図例があるのでブログネタがつきませんね。

今回は前回の作図結果をカラーバンドを配置して、行ごとに塗り分けて表を見やすくしたい場合はどうするかを紹介します。

GTLでフォレストプロットを作成する (1)フォレストプロットはリスク比やハザード比を視覚化するときによく使われます。臨床研究では頻出の作図ですので押さえておくと後々楽です。 ...

偶数行または奇数行ごとにカラーバンドを配置する。

excelのテーブルで各行に塗りが適用されて縞模様になっているテーブルをご覧になったことがあるかと思います。これをGTLで実現するにはdiscreteoptオプションでcolorbandsオプションを指定すれば実現できます。
ただしこれは離散軸のみ使用可能です。そのため軸変数が数値になっている場合は「type=discrete」の記述を追加する必要があります。

/* invention total */ 
layout overlay / walldisplay=none xaxisopts=(display=none)
   yaxisopts=(display=none reverse=true type=discrete 
      discreteopts=(colorbands=odd colorbandattrs=(塗りの定義)
   ));

   axistable y=ID value=COL3 / 
      valuejustify=right 
      valueattrs=(size=10) 
      pad=(left=30) 
      display=(values) ; 

endlayout;

oddを指定すると偶数行を、evenで奇数行を塗ることができます。色の指定を指定したい場合はcolorbandattrsオプションで定義できます。
上記のコードを基に前回の作図コードを修正すると以下のようになります。

実行結果

今回はlatticeレイアウトで各列を定義しているので各列の間に白い線が入ります。一つのレイアウトブロック内に複数のaxistableを設置する場合はこのようなことは起こらないのですが、その場合は各列の幅を調整することはできなくなります。

試しに列タイトルをaxistableのラベルで代用し、すべての列を一つのレイアウトブロック内に配置すると以下のようになります。列タイトルは列データを格納した変数にラベルを付与すると任意の文字列を表示できます。

proc template; 
define statgraph forest; 
begingraph; 

discreteattrmap name="dot"; 
   value "1" / markerattrs=GraphData1(symbol=squarefilled); 
   value "2" / markerattrs=GraphData2(symbol=diamondfilled) textattrs=(weight=bold); 
enddiscreteattrmap; 

discreteattrvar var=grp attrvar=_grp attrmap="dot"; 

entryfootnote halign=left "Heterogenity: Chi_square = 22.20, df=7 (p=0.002), I"{sup "2"}"=68%" / ; entryfootnote halign=left "Test for overall effect: Z=2.00 (p=0.05)"; 

layout overlay / walldisplay=none 
   xaxisopts=(type=log logopts=(viewmin=0.01 viewmax=100)) 
   yaxisopts=(display=none reverse=true type=discrete
      discreteopts=(colorbands=odd));

 innermargin / align=left;
   /*テーブルの定義*/ 

   axistable y=ID value=COL1 / 
      textgroup=_grp 
      valuejustify=left 
      valueattrs=(size=10) 
      display=(values label) 
      labelattrs=(size=12); 

   axistable y=ID value=COL2 / 
      valuejustify=right 
      valueattrs=(size=10) 
      pad=(left=25) 
      display=(values label) 
      labelattrs=(size=12); 

   axistable y=ID value=COL3 / 
      valuejustify=right 
      valueattrs=(size=10) 
      pad=(left=30) 
      display=(values label) 
      labelattrs=(size=12); 

   axistable y=ID value=COL4 / 
     valuejustify=right 
     valueattrs=(size=10) 
     pad=(left=25) 
     display=(values label) 
     labelattrs=(size=12); 

   axistable y=ID value=COL5 / 
     valuejustify=right 
     valueattrs=(size=10) 
     pad=(left=30) 
     display=(values label) 
     labelattrs=(size=12); 

   axistable y=ID value=COL6 / 
     valuejustify=right 
     valueattrs=(size=10) 
     pad=(left=20) 
     display=(values label) 
     labelattrs=(size=12); 

   axistable y=ID value=COL7 / 
     valuejustify=left 
     valueattrs=(size=10) 
     pad=(left=20) 
     display=(values label) 
     labelattrs=(size=12); 

   axistable y=ID value=COL8 / 
     valuejustify=left 
     valueattrs=(size=10) 
     pad=(left=15) 
     display=(values label) 
     labelattrs=(size=12); 

endinnermargin; 

   scatterplot x=odds_ratio y=ID / 
      group=_grp
      xerrorlower=lower 
      xerrorupper=upper 
      sizeresponse=total 
      errorbarcapshape=none; 

   referenceline x=1; 

endlayout; 
endgraph; 
end; 
run;

各列の白い線はなくなりましたが、代わりに列幅が勝手に設定されます。axistableの列ラベルを2段に表示するオプションはないため、列ラベルが長いと体裁が崩れやすいです。簡単な表だったらこれでもよさそうですが、列タイトルをきれいに成形したいのであればちょっと厳しい。列ラベルを使わないでentryステートメントを使えば柔軟にタイトルを配置できますが、axistableの列幅が設定できないとかなり自由度が制限されます。

axistableの列幅は列ラベル名と列内の文字列の長さによって自動的に決定されます。また列ラベル名に半角スペースがある場合はそこで改行されるようです。半角スペースを駆使すれば列幅もある程度制御できそうです。

latticeで列を一つ一つ定義するよりはこちらの方がコードがすくなくすむので、シンプルな列タイトルであればlatticeを使わないほうが楽ですね。ただし列を二段にしたり罫線をいれたりしたいときはlatticeを使ったほうがよさそうです。

referencelineで任意の行にカラーバンドを配置する

colorbandsオプションで行を色分けすると偶数行、奇数行の2パターンしか扱えないので不便です。そこでreferencelineを重ねて特定の行のみを色を塗る方法を試します。線の太さを行の高さと同じにすれば行全体を塗ることができます。新規に変数を作れば塗りの有無も制御できるので、これが一番実用的な方法だと思います。

統合解析の行のみ(Total, total events)の行だけを塗ってみます。

まずTotalまたはtotal eventsのレコードの場合変数fillにIDの値を格納します。IDは今回はY軸の変数です。それ以外のレコードの場合fillは欠損値となります。欠損値の場合は何も作図されません。

次に各列のaxistableまたはscatterplotステートメントの上にreferencelineステートメントを追加します。y軸変数は先ほど作成した変数fillを指定します。線の太さはlineattrsオプションで行の高さと同じ幅を指定します。こうすると行全体を塗ることができます。

/* invention events */ 
layout overlay / walldisplay=none 
   xaxisopts=(display=none) 
   yaxisopts=(display=none reverse=true type=discrete); 

referenceline y=fill / 
   lineattrs=(thickness=25 color=cxc5cff9) ; 

axistable y=ID value=COL2 / 
   valuejustify=right
   valueattrs=(size=10) 
   pad=(left=25) 
   display=(values) ; 

endlayout;

修正して実行すると以下のようになります。

実行結果

統合解析の行のみを塗ることができました。塗りを定義する変数を複数用意すれば行全体以外にも任意のセルを塗ることができるため汎用性はかなり高いでしょう。

まとめ

axistableの各行を塗り分けたい場合はrererencelineを使うと便利です。列タイトルを凝ったデザインにしたい場合はlatticeレイアウトで各列を1つずつ配置する方法の方が便利かもしれません。

次の記事はこちら

GTLでフォレストプロットを作成する (4)列データにインデントを適用する今回もフォレストプロットの話です。 前回の記事はこちら https://picolabs.jp/SAS-GTL-forestpl...