2019年9月4日

SANKEY DIAGRAMに余白をつくる

最終更新: 2019年9月6日

この記事は以下のSankey Diagram作成ガイドの続編であり、以下の記事を前提としています。

TABLEAUでSANKEY DIAGRAMを作る

表題の通り、今回はSankey Diagramのアイテム間に余白を作る方法について解説します。

今回の記事に使用したWorkbookは以下からダウンロードできます。

https://tabsoft.co/2Z3lChJ


基本方針

やり方は色々あると思いますが、今回は「ある大きさの余白を、各アイテムに分配し、Sankeyの両側で高さが変わらないように設計」します。

要は余白を用意して、右側or左側の(ディメンション内の個数-1)で等分して、差し込むイメージです。

ということで、余白のサイズはパラメータで用意するわけですが、この余白分だけSankeyに使用した様々な表計算、具体的にはMax/Min Positionあたりを修正しなければなりません。

この修正が若干厄介です。

例えば左側のオレンジの3本に注目します。

余白無しバージョンに比べ、各帯の位置が(2/3)余白だけ上にズレています。

更に具体的に言うと、各帯の下端と上端に、Sankeyの計算式の結果+(2/3)余白が足されています。

逆に言えば、チャレンジはそこだけです。

分かってしまえば難しくはないはずです。きっと。


計算式を見る

ということで、最初に修正版の計算式を一通りお見せします。

Dimension 1についての式のみを挙げていますが、Dimension 2についても基本は同じです。Dimension 1と2を入れ替えてあげればいいだけです。

ここで[Margin]は数値型のパラメータです。

先に概要だけ説明すると

  • Wrapの式でRUNNING_SUMを取っているので、Dimension 1のアイテムで区別されたPolygonについて、各Dimension 1について1点だけMarginを与えるように設計しなければならない。これをLAST()を用いて制御(Margin 1の式のIIF()部分を参照)。

  • 余白をDimension内のアイテム個数で等分(Margin 1の式の分母を参照)。

  • 余白をMin/Max Positionに追加

  • RUNNING_SUMにより、余白が割り当てられている点は余白が2回アサインされてしまう。なのでWINDOW_MAX([Margin 1])で修正。

という流れになります。

正直なんのこっちゃという感じなので、一つ一つ見ていきましょう。

(ちなみに、今回はワークブックと記事を見ながら、手を動かしてみることを強くオススメします。表計算は眺めるよりも作ってみる方が早いです。)


LAST 1とMargin 1について

LAST 1はシンプルにLAST()です。

LAST 1

LAST()

表計算を上記の表のように設定すると、下図のようにLAST 1はアサインされます(テキストラベル参照)。

このLAST 1を使ってMargin 1を計算します。

Margin 1

IIF([LAST 1] = 0,[Margin],0)

/MIN({COUNTD([Dimension 1])-1})

この計算フィールドの意味するところは「LAST 1が0であればMarginを等分した数値を割り当てる」です。

つまり、各色のPolygonについて、最上段Polygonの上端だけに余白が割り当てられます。


MIN/MAX POSITIONについて

続いてMin Positionについて見てみます。

Min Position 1 (margin)

RUNNING_SUM([Max for Min Position 1] + [Margin 1]) - [Sankey Arm Size]

ちなみにMax for Min Position 1は以下です。余白無しSankeyと同じです。

Max for Min Position 1

RUNNING_SUM([Sankey Arm Size])

上記については、単にMin Positionの中にMargin 1を追加し、合わせてRUNNING_SUMをとっているのみです。

ところで、実はこの式をそのままWrapに投げてしまうと、各Polygonの位置がおかしくなります(下図参照)。

ということで、LAST 1 = 0でMarginが重複している箇所について補正します。

Min Position 1 Wrap (margin)

WINDOW_SUM([Min Position 1 (margin)]) - WINDOW_MAX([Margin 1])

WINDOW_SUMで最終的に[Margin 1]が2回カウントされる形になるので、それぞれに割り当てられているMargin 1を、各Polygonの各点から引きます。

これを許しているのがPath Frameに沿ったWINDOW_MAX([Margin 1]) の補正項です。

(Path Frameに沿った計算であることが重要)

Max Positionについても同様の議論がされますので、計算式の紹介に留めます。

Max Position 1 (margin)

RUNNING_SUM([Sankey Arm Size] + [Margin 1])

Max Position 1 Wrap (margin)

WINDOW_SUM([Max Position 1 (margin)]) - WINDOW_MAX([Margin 1])


Sankey Polygonをつくる

Margin使用した上記の計算フィールドを、Sankey Polygonの式にそのまま使用します。

Sankey Polygons (margin)

IF [Path Index] > 49 // ポリゴンの上半分を描画

THEN [Max Position 1 Wrap (margin)]

+ ([Max Position 2 Wrap (margin)] - [Max Position 1 Wrap (margin)])

* [Sigmoid]

ELSE [Min Position 1 Wrap (margin)]

+ ([Min Position 2 Wrap (margin)] - [Min Position 1 Wrap (margin)])

* [Sigmoid]

END

このあとのVizの作り方は、前回の記事と全く同じなので割愛します。

ここまでで余白つきSankey Diagramは完成です。


SANKEY DIAGRAM両端のラベルを作る

最後の仕上げです。Sankey両端、Dimension 1とDimension 2を作成するラベルを作成します。

先に概観だけお見せすると、Gantt Cahrtで作ります。

Bar Size

-[Chosen Measure]/TOTAL([Chosen Measure])

Bar 1

RUNNING_SUM([Chosen Measure]/TOTAL([Chosen Measure]))

+[Margin] / MIN({COUNTD([Dimension 1])-1}) * (INDEX()-1)

Bar Sizeは、Dimension 1の各アイテムの、全体における割合を示しています。

Bar 1は「全体における割合」の累計(RUNNING_SUM)を出した後に「等分された余白×Dimension 1の累計アイテム数」を足しています。

累計はINDEXで行いましたが、このあたりの実装はもう少し分かりやすくできそうですね。

Gantt Chartにラベルを付けてもいいのですが、あえて別ワークシートを作成し、ラベルを工夫してみます。こういう実装もできますよね、ということで。

透明なGantt Chartを用意します。

ここでLabel用に位置を調整した計算フィールドを用意します。

Bar 1 (Label)

[Bar 1] - [Chosen Measure]/TOTAL([Chosen Measure])/2

要は「Bar 1から割合の半分を引く→Ganttの位置が、Bar 1に比べて半分になる」というだけです。

Bar 1とBar 1 (Label)を並べた結果がこちらです。

同様のものをDimension 2にも作ってあげれば、以下のようにSankey Diagramが作成できます。


最後に

念願の「前処理不要のSankey Diagramに余白を付ける」ことに成功しました。

余白のパワーは偉大で、やっぱり見やすくなるんですよね。

計算フィールドも余白無し版に比べて大きな修正はないので、今後はこちらをスタンダードにしていこうと思います。

ご質問等はTwitterまたはLinkedinまでよろしくお願いします。 それでは。