SAS

SASで複数行の項目軸を作成する

棒グラフのような項目別にプロットする場合、項目のグループを軸に表示したいときがあります。
Excelではピボットグラフの機能で項目軸を複数行に設定してグラフを作成することができますが、
SASの場合はそのような機能はありませんので各項目ラベルを表示位置を手動で設定する必要があります。

データ前処理

以下のようなテストデータがあります。

変数名 定義
ptcd MedDRA PTコード
pt PT日本語
group 治療群
grade 重症度グレード
percent 群全体に対する有害事象(PTコード)の発現割合(%)

各有害事象、治療群および重症度グレードごとに発現割合を積み上げ棒グラフで表現してみます。

項目軸は複数行設定する機能はGTLにはないため、項目ラベルの文字列とその表示位置を計算する必要があります。

今回は項目に連番を付与した作図用軸変数を用意し、この軸変数の値を基にラベル位置を計算します。

有害事象(PT)は GroupA~GroupCの棒グラフの下部の中央付近に表示させます。また区切り線の表示位置も計算します。
今回はgroup Cの右隣に垂直線を引くようにしました。

data wk2;
set wk1;
by ptcd group;
*x= 棒グラフ用の項目変数、連番を振っているだけ;
*grp_x grp_y = 治療群ラベルの表示位置;
*pt_x pt_y = 有害事象ラベルの表示位置;
*ref_x=参照線の表示位置、ただし左端の参照線はデータに依らず固定なので、テンプレート上で直接数値を指定;
retain x x_fst 0;
if first.group then do;
x+1;
grp_x = x;
grp_y=2;
end;
if first.ptcd then x_fst=x;
if last.ptcd then do;
pt_x = (x+x_fst) / 2;
pt_y=1;
ref_x = x+0.5;
end;
drop x_fst;
run;

テンプレート

項目軸は棒グラフとは別のプロットエリアに作図することになりますので、プロットエリアを2行に分割します。1行目は棒グラフ、2行目は項目軸を表示します。
なお作図用に作成した軸はただの連番で意味はないため、非表示とします。

ポイントはX軸の軸タイプをlinearに設定することです。linearにすることで各項目の間にも目盛りが存在することになり、棒グラフの間にもオブジェクトを挿入することができます。
また子要素のlayout overlayではなくcolumnaxes, rowaxesステートメントで軸の設定をするのもポイントです。こうすることで棒グラフのプロットエリアと項目軸のプロットエリアの隙間がなくなります。

項目ラベルはtextplotを使用して作成します。axistableを使用しても同じことができますが、axistableはテキストの回転ができないためtextplotを使ったほうが汎用性が高いです。
textplotは表示したい文字列に空白が入ると表示位置が空白の分だけずれてしまうため、eval関数とstrip関数を用いて作図前に不要な空白を削除します。

Copy
proc template; define statgraph hierarchical; begingraph; layout lattice / rows=2 rowweights=(0.9 0.1) columndatarange=union rowdatarange=union ; /*軸設定 項目軸の軸タイプは必ずlinear*/ columnaxes; columnaxis / type=linear display=none linearopts=(viewmin=0 viewmax=10) offsetmin=0 offsetmax=0; endcolumnaxes; rowaxes; rowaxis / linearopts=(tickvaluesequence=(start=0 end=75 increment=25) viewmin=0 viewmax=75); rowaxis / display=none; endrowaxes; /*棒グラフ*/ layout overlay ; barchartparm category=x response=percent / group=grade groupdisplay=stack name="bar" ; endlayout; /*項目軸*/ layout overlay / walldisplay=none ; /*項目ラベル、作図前に余分な空白を削除する*/ textplot x=grp_x y=grp_y text=eval(strip(group)) ; textplot x=pt_x y=pt_y text=eval(strip(pt)) / textattrs=(size=10); /*区切り線*/ referenceline x=0.5 / lineattrs=(color=black); referenceline x=ref_x / lineattrs=(color=black); endlayout; /*凡例*/ sidebar / align=bottom spacefill=false; discretelegend "bar"; endsidebar; endlayout; endgraph; end; run; proc sgrender data=wk2 template=hierarchical; run;

referencelineだと線がプロットエリア全体に作成されますが、vectorplotを使用すれば区切り線を任意の位置に配置できます。
2行以上の項目軸ならvectorplotのほうが便利かもしれません。