「SAS Plotter」はモダンなグラフを簡単に作成できるグラフマクロパッケージです。
このページではSAS Plotter Ver1.20でサンキーダイアグラムを作成する方法を解説します。
https://picolabs.jp/sasplotter_usage
サンキーダイアグラムとは
サンキーダイアグラムはネットワーク図の一種で、一般的にエネルギーや資金の流れを視覚化する際に用いられます。
流れは矢印などの図形で表現され、その太さで流量を表現することが一般的のようです。
疫学研究において、サンキーダイアグラムは使用薬剤や傷病の状態といった患者の状態変化を可視化する際に用いられています。
SASにおけるサンキーダイアグラムは過去に以下の作成例が報告されています。
それに対しSAS plotterのマクロは他のソフトと同様の体裁のものが作成できることに加え、
各オブジェクトの表示位置や体裁の調整を可能にし、特定のノードを強調表示させることが可能になっています。
性能面では他のソフトウェアと比べて低機能ではありますが、シンプルなサンキーダイアグラムであれば、他ソフトと併用しなくてもSAS BaseとSAS GRAPH環境のみで作成できます。
とはいえSASでなければだめというわけではないのであれば、素直にRやtableau等のソフトを使うことを推奨します。
またjavascriptライブラリとSASのputステートメントを併用して、SASからサンキーダイアグラムをHTML形式で出力する事例が紹介されています。
HTMLで問題なければこちらのほうが応用が利くでしょう。
本マクロにおいてサンキーダイアグラムは3つの要素で構成されています。
ドメイン
X軸に対応する変数です。例えば測定時点などが該当します。
ノード
各ドメインにおけるカテゴリを表現します。本マクロでは長方形として表現されています。例えば特定時点の患者の使用薬剤などがノードに相当します。ノードは各ドメインにいずれかに必ず属します。
リンク
ノード同士を接続します。本マクロではシグモイド曲線の帯として表現され、帯の太さがそのリンクに属する要素の量を表現します。
作図にもよりますが、リンクは基本的に方向が決まっており左から右へ接続されます。リンクの左側ノードは「ソースノード」、右側のノードは「ターゲットノード」と呼びます。
例えばday0ではDrugAを使用していた患者集団が30日後にDrugBに切り替えた場合、 day0ドメインのノード「Drug A」とday30ドメインのノード「DrugB」はリンクによって接続されます。
「DrugA」はソースノード、「DrugB」はターゲットノードです。このリンクに属する患者数が多いほどリンクの形状は太くなります。
Input data
任意のドメイン変数を用意します。ドメイン変数にはそのドメインに対応するノードカテゴリを格納します。必ず数値変数に設定してください。
ドメイン変数にはノードカテゴリのフォーマットを適用することを推奨します。
domain1 | domain2 | domain3 |
---|---|---|
node A | node B | node C |
node B | node A | node C |
node D | node A | node B |
文法
ods graphics / < graphics option > ;
ods listing gpath=< output path >;
%macro sankey(
data=,
domain=,
domainfmt=,
domaintextattrs=(color=black size=11),
gap=5,
nodefmt=auto,
nodewidth=0.2,
nodeattrs=auto,
nodename=true,
nodetextattrs=(color=black size=9),
linktext=true,
linktext_offset=0.05,
linkattrs=auto,
linktextattrs=(color=black size=8),
reverse=false,
focus=None,
endFollowup=None,
stat=both,
unit=,
legend=false,
palette=sns);
パラメータ
data : データセット名(必須)
入力データセット。keep, renameおよびwhereオプションが利用可能です。
ドメインパラメータ
domain : 変数名 (必須)
ドメイン変数を指定します。変数は任意の変数をリンクされる順番で指定してください。例えば「var1 var2 var3」と指定した場合、var1→var2→var3の順序でリンクされます
domainfmt : フォーマット名 (必須)
ドメイン変数に割り当てるフォーマットを指定します。フォーマットは必ずworkライブラリに保存し、コード値は数値にする必要があります。フォーマットで定義されたラベルが表示されます。
domaintextattrs : テキストの体裁 (オプション)
ドメインのテキストの体裁を指定します。GTLのtextattrsオプションと同様 の項目(size, color, weight, style)が指定可能です。デフォルトは(size=11 color=black)。
ノードパラメータ
gap : 数値 (オプション)
同一ドメイン内のノードの間隔を指定します。デフォルトは5。
nodefmt : キーワードまたはフォーマット名 (オプション)
ノード名のフォーマットを指定します。”auto”に指定した場合は、フォーマットは入力データのドメイン変数から取得します。入力データに存在しないノードを凡例に表示させる場合や、異なるデータからそれぞれ作図する場合はフォーマットを指定したほうが良いでしょう。フォーマットはworkライブラリに保存する必要があります。デフォルトは”auto”.
nodewidth : 数値 (オプション)
ノードの図形の幅を指定します。数値を大きくするとノードの図形の幅が広がります。デフォルトは0.2。
nodeattrs : キーワードまたは塗りの体裁(オプション)
ノードの塗りを設定します。”auto”の場合はノードのカテゴリに応じて塗分けされます。GTLのfillattrsの同様の設定(color, transparency)を指定するとすべてのノードが同じ体裁に変更されます。
例えば以下のように設定するとすべてのノードは青色になります。デフォルトは”auto”
nodename : 真偽値(オプション)
ノード名(ノードカテゴリの名前)の表示を切り替えます。デフォルトは”Tuue”。
nodetextattrs :テキストの体裁 (オプション)
ノードのテキストの体裁を指定します。GTLのtextattrsオプションと同様 の項目(size, color, weight, style)が指定可能です。デフォルトは(size=9 color=black)。
リンクパラメータ
linkattrs : 塗の体裁 (オプション)
リンク図形の塗りを設定します。”auto”の場合はソースノードのノードカテゴリに応じて塗分けられます。GTLのfillattrsの同様の設定(color, transparency)を指定するとすべてのリンクが同じ体裁に変更されます。
デフォルトは”auto”。
linktext : 真偽値(オプション)
リンクテキスト(頻度および割合)の表示を切り替えます。リンクテキストはソースノードの近くに表示されます。デフォルトは”Tuue”。
linktext_offset : 数値 (オプション)
ノードとリンクテキストの間隔を指定します。デフォルトは0.5。
linktextattrs : テキストの体裁 (オプション)
リンクのテキストの体裁を指定します。GTLのtextattrsオプションと同様 の項目(size, color, weight, style)が指定可能です。デフォルトは(size=8 color=black)。
その他のパラメータ
reverse: 真偽値(オプション)
Trueに設定するとy軸を反転させます。デフォルトは”false”。
focus : 条件式 (オプション)
強調表示するリンクを条件式で指定します。条件式は以下の変数が使用可能です。コード値は入力データまたはフォーマットオプションで指定したフォーマットのコード値です。
source_node=nodeのコード値
target_node=nodeのコード値
domain=domainのコード値
next_domain=domainのコード値
条件式を指定すると、条件に合致しないノードをソースとするリンクはすべてグレー表示となり、リンクテキスト表示は無効化されます。
例えば2番目のドメインのうちコード値=1をソースノードとするリンクを強調したい場合は以下のように指定します。
focus=(source_node=1 and domain=2)
デフォルトはnone(強調表示はしない)。
EndFollowup : ノードのコード値(オプション)
フォローアップ終了を示すコード値を指定します。指定するとフォローアップ終了のノードはグレー表示となります。さらにドメイン毎のフォローアップ中の症例数とその割合をサンキーダイアグラムの下部に表示します。
stat : キーワード (オプション)
ノードとリンクに表示される統計情報の内容を指定します。キーワードは以下のものが利用可能です。デフォルトは”both”。
割合は入力データセットのオブザベーション数に対する割合となります。
- FREQ: 頻度
- PCT: 割合(小数第二位まで表示)
- BOTH: 頻度と割合
- NONE: 統計情報は表示しない
unit : テキスト(オプション)
頻度の表示を有効にした場合、頻度の単位(接尾辞)を指定します。例えば「例」を指定した場合は頻度表示は「123例」といった感じで表示されます。
デフォルトは””(欠損)。
legend : 真偽値(オプション)
Trueの場合は群の凡例を表示します。デフォルトはTrue。
pallete : キーワード (オプション)
塗り、ライン、マーカーのカラーパレット、以下のパレットが利用可能です。デフォルトはSNS(seabornのデフォルトパレット)
- SAS
- SNS (Seaborn)
- STATA
- TABLEAU
作図例
基本的なサンキーダイアグラム
各症例の治療計画(Regimen A~Regimen I)の時間変化を可視化します。
起点日、起点日から30, 60日後の各症例の治療計画を記録したデータを使用します。
proc format;
value domainf
1="day0"
2="day30"
3="day60"
4="day120";
value nodef
0="Regimen A"
1="Regimen B"
2="Regimen C"
3="Regimen D"
4="Regimen E"
5="Regimen F"
6="Regimen G"
7="Regimen H"
8="Regimen I"
;
run;
data graph;
set raw;
format day0 day30 day60 day120 nodef.;
run;
ods graphics / height=15cm width=20cm imagefmt=svg imagename="sankey_basic" noborder;
ods listing gpath="<output path>";
%sankey(
data=graph,
domain=day0 day30 day60,
domainfmt=domainf
);
ドメイン間隔の調整
ドメインの間隔はドメイン変数に適用するフォーマットのコード値に依存します。コード値を調整することで特定のドメインの間隔を調整することが可能です。
例えばコード値を以下のように調整したうえで前項のプログラムを再実行すると、day30とday60の間隔を広げています。
proc format;
value domainf 1="day0"
2="day30"
4="day60"
8="day120";
run;
ノードのフォーマットと凡例
以下は「基本的なサンキーダイアグラム」のプログラムを修正し、day0とday30のダイアグラムを出力した結果です。修正前と比較すると同じノードなのにも関わらずRegimen E, G Iの色が変わってしまっていることがわかります。デフォルトでは入力データセットに存在するカテゴリに対して順番に色を割り当てているため、同じノードカテゴリであってもデータセットを変更すると勝手に色が変更されてしまいます。
また判定に表示される要素も入力データセットに存在するカテゴリのみ表示されます。
これを防ぐにはnodefmtオプションでノードカテゴリのフォーマットを指定すると良いでしょう。データセットを変更してもノードには一貫した色が割り当てられます。
また凡例にはフォーマットに登録されたすべての要素が表示されます。
nodefmtオプションを設定して再実行した結果は以下の通りです。ノードの色はデータに存在するノードの順ではなくフォーマットに存在する順に色が割り当てられます。さらに凡例もフォーマットに定義されたすべてのRegimenが表示されています。
%sankey(
data=raw,
domain=day0 day30,
domainfmt=domainf,
legend=true );
塗りの体裁調整
デフォルトではノードとリンクの色はノードカテゴリに基づいて決定されています。nodeattrsまたはlinkattrsを設定するとすべてのノードまたはリンクの塗りが同じものに統一されます。
%sankey(
data=raw,
domain=day0 day30 day60 ,
domainfmt=domainf,
nodeattrs=(color=grey) );
%sankey(
data=raw,
domain=day0 day30 day60 ,
domainfmt=domainf,
linkattrs=(color=skyblue transparency=0.7)
);
テキストの体裁調整
domaintextattrs、nodetextattrsおよびlinktextattrsパラメータはドメイン、ノード、リンクのテキストの体裁を変更するのに便利です。
GTLのtextattrsオプションと同じ指定が可能です。
%sankey(
data=raw,
domain=day0 day30 day60,
domainfmt=domainf,
nodeattrs=(color=grey),
linkattrs=(color=skyblue transparency=0.7),
domaintextattrs=(color=red size=12),
nodetextattrs=(color=blue size=12),
linktext_offset=0.15,
linktextattrs=(color=green size=8)
);
focusパラメータ
focusパラメータは特定のノードに着目したい場合に便利です。focusパラメータの条件式に合致しないノードをソースとするリンクはすべてグレー表示となり、リンクテキストが無効化されます。
以下の論文では特定のノードのみを強調表示した「focused sankey plot」が紹介されています。これと同じ作図をSAS plotterで作成してみます。
Drug Aを強調したいので、focusパラメータにDrug Aのコード値である1を条件式に設定します。条件式はdomainとnodeに対する条件式のみ設定できます。Drug AからDrug Dを上から配置するため、reverseオプションでY軸を反転させています。
proc format;
proc format;
value domainf
1="day 0"
2="day 30"
3="day 60"
4="day 90";
value nodef
1="Drug A"
2="Drug B"
3="Drug C"
4="Drug D"
5="Lost to Follow-up"
;
run;
data graph;
set raw;
format var1-var4 nodef.;
run;
例1:Drug Aをソースノードとするリンク
ods graphics / height=20cm width=25cm imagefmt=svg imagename="sankey_focus" noborder;
ods listing gpath="<output path>";
%sankey(
data=raw,
focus=(source_node=1),
domain=var1 var2 var3 var4,
domainfmt=domainf,
gap=1,
reverse=true,
nodewidth=0.1,
nodename=false,
stat=freq,
legend=true,
linktext_offset=0.03,
palette=sns);
例2:Lost to followupをターゲットノードとするリンク
focus=(target_node=5)
例3:ドメイン2(day 30)のノードをソースとするリンク
focus=(domain=2)
例4:複数条件を適用
focus=((domain=1 and source_node=2) or (next_domain=4 and target_node=5))
endFollowupパラメータ
endFollowupパラメータにフォローアップ終了を示すノードのコード値を指定すると、指定したノードはグレーに表示されます。各ドメインのフォローアップ中の症例数と割合をサンキーダイアグラムの下部に表示します。
フォローアップ終了した症例数は、各ドメイン毎のendFollowupパラメータで指定したコード値のノードに該当するレコード数となります。
割合は以下の数式で算出されます。
% followup = (入力データセットのレコード数 – endFollowupパラメータで指定したコード値のノードに該当するレコード数) / 入力データセットのレコード数 * 100
ods graphics / height=20cm width=25cm imagefmt=svg imagename="sankey_endfollowup" noborder;
ods listing gpath="<output path>";
%sankey(
data=raw,
domain=var1 var2 var3 var4,
domainfmt=domainf,
gap=1,
reverse=true,
nodewidth=0.1,
nodename=false,
stat=freq,
legend=true,
linktext_offset=0.03,
endfollowup=5,
palette=sns);