(2021/5/27 追記: もっと簡単に作る方法を書きました)
この記事はInformation Labの以下の記事に関する勉強ノートです。
雑に完成させた、自分のVizはこちらに。計算式に困ったときに役立つかもしれません。
・そもそもSankey Diagramって?
ここではSankey自体の解説はしませんが、日本語で解説されている記事がこちらにあります。まずざっくりとこちらの記事に目を通されることをおすすめします。
もしくは、英語でざっくりと解説した自分のVizがこちらに。
・どうしてデータ加工のないSankeyがありがたいの?
Sankeyを作る過程で、下記のようなデータ加工が必要になります。これ、恐ろしいことに、下段の表を、元データの各レコード全てにくっつけます。その結果、データサイズが凡そ100倍されます。2桁オーダーが上がるのは、場合によっては好ましくないですね。
ちなみに、下図の下段データ(加工用データと呼ぶことにします)は、以下の説明で使います。列名と中身を頭に留めて頂けるとありがたいです。
・本題:データ加工のないSankey Diagramを作ってみよう。
というわけで作ります。元リンクの記事を読めば作れますが、日本語への翻訳、かつ適宜自分なりの解説を入れながらいきます。使用データは英語版SuperStoreです。
Step 1.Sankeyで流れを分けるための”流入元”と”流入先”、そして”流れの大きさ”の計算に用いる計算フィールドを作成。
Dimension 1 CASE [Select Dimension 1] WHEN 1 THEN [Region] WHEN 2 THEN [Category] WHEN 3 THEN [Sub-Category] WHEN 4 THEN [Segment] WHEN 5 THEN [Ship Mode] END
Dimension 2 CASE [Select Dimension 2] WHEN 1 THEN [Region] WHEN 2 THEN [Category] WHEN 3 THEN [Sub-Category] WHEN 4 THEN [Segment] WHEN 5 THEN [Ship Mode] END
Chosen Measure [Sales]
ここでは、Select Dimension 1とSelect Dimension 2という、整数型パラメータ2つを用意しておいてください。
Dimension1が流入元(Sankey左側)、2が流入先(Sankey右側)のためのものです。
Step 2.Data Densificationを行う。
従来の、データ加工を行うSankeyの話に戻ります。あのJOINで何をやっているかというと、Sankeyの曲線は列"t"に沿った、Sigmoid曲線というものを用いて作ります。
従って曲線の流れ、大きさを与えてやるために、各tにそれぞれデータ点が必要でした。そのデータ点の順番を表すのが、加工用データにおける列”Path”です。
これをデータ加工無しでそうやるか。これはちょっと上級ですが「Data Densification」という方法を取ります。ここでは紹介しませんが、要は「疑似的にデータ件数を増やす」ぐらいのイメージで良いと思います。僕も厳密な理解はできていません。
で、どうやるかですが、加工用データの”Path”に該当するものを2ステップで作成します。
Path Frame IF [Chosen Measure] = {FIXED : MIN([Chosen Measure])} THEN 0 ELSE 97 END
Path Frame (bin)
PathFrameの説明をします。この計算でしていることは「あるデータ点のChosen Measureの値が、データセット全体での最小値と一致するなら、0を返してね。それ以外なら97を返してね。」ということです。データ点に無理矢理0と97というラベルを与えています。
それをサイズ1のビンを作ることにより疑似的に0 - 97の整数を作り出しています。
このPathFrameの計算や、Binの分布に何の意味もありません。大事なのは、この操作によって、疑似的に0 - 97の整数列を作り出せる、というだけです。そしてその整数列は、加工用データの”Path”と同じ役割を果たせます。
Step 3.INDEX
Path Indexという計算式を用意します。これはPath Frame(bin)に沿って計算するようにしてください。
この文章でパッと来ない方、後で設定しますので大丈夫です。パッと来る方、以下のようにすると楽です。
Step 4.Sigmoid関数まわりを作成
Sigmoid関数は-6~6の実数tの関数として作るので、まずは変数tを作成します。
T IF [Path Index] < 50 THEN (([Path Index]-1)%49)/4-6 ELSE 12 - (([Path Index]-1)%49)/4-6 END
Path Indexが50以下のとき、"[Path Index]-1"は0から48の間です。
"([Path Index]-1)%49"は、[Path Index]-1を49で割ったときの余りを返します。[Path Index]-1が49未満なので、もちろん値がそのまま余りになります。
"(([Path Index]-1)%49)/4"は、0から48を4で割った数なので、もちろん0から12の間です。それを6で引くので、"(([Path Index]-1)%49)/4 - 6"は-6から6の間ですね。
([Path Index] が50以上の時も、同様です。)
したがって、ここでもなんと、加工用データで頑張って作っていた、-6から6を取る変数tを、こんなスマートな方法で作成することができました。感動しました。
そしておなじみSigmoidは以下です。
Sigmoid 1/(1+EXP(1)^-[T])
Step 5.Sankeyの流れの大きさの計算式
Sankey Arm Size SUM([Chosen Measure])/TOTAL(SUM([Chosen Measure]))
要は全体に対する割合ですね。
Step 6.Sankeyポリゴンの、上部に関する計算式
作成するSanekyはポリゴン”多角形”マークで作成するので、上半分と下半分に関する計算が必要です。まず上半分の計算を用意します。
(上とか下のイメージが掴めない方は、参考までにこちらをどうぞ。https://public.tableau.com/profile/yoshitaka6076#!/vizhome/SankeyDiagramwithPolygon/PolygonSankeyChart)
Max Position 1 RUNNING_SUM([Sankey Arm Size])
Max Position 1 Wrap WINDOW_SUM([Max Position 1])
Max Position 2 RUNNING_SUM([Sankey Arm Size])
Max Position 2 Wrap WINDOW_SUM([Max Position 2])
Step 7.Sankeyポリゴンの、下部に関する計算式
Max for Min Position 1 RUNNING_SUM([Sankey Arm Size])
Min Position 1 RUNNING_SUM([Max for Min Position 1])-[Sankey Arm Size]
Min Position 1 Wrap WINDOW_SUM([Min Position 1])
Max for Min Position 2 RUNNING_SUM([Sankey Arm Size])
Min Position 2 RUNNING_SUM([Max for Min Position 2])-[Sankey Arm Size]
Min Position 2 Wrap WINDOW_SUM([Min Position 2])
メモ:なぜWrapの計算が必要か。
元々のSankeyは、Wrapの計算式はありませんでした(RUNNING_SUMで終わっていて、それのWINDOW_SUMをとっていなかった)。
この点について、どう解説したらいいか分かりませんが、流れの大きさをつど計算するため、各tでMAX/MIN Positionの情報を与えるには、WINDOW_SUMで全てのtについてMAX/MIN Positionの値を付与するしかなかったのかな、という感じです。
実際に、データ加工あり(左)とデータ加工なし(右)のSankeyを見てみると、Tがー6.0以外では、MAX/MIN Positionは値がありません。
Step 8.Sankeyポリゴンの計算
Sankey Polygons IF [Path Index] > 49 THEN [Max Position 1 Wrap]+([Max Position 2 Wrap]-[Max Position 1 Wrap])*[Sigmoid] ELSE [Min Position 1 Wrap]+([Min Position 2 Wrap]-[Min Position 1 Wrap])*[Sigmoid] END
Step 9.Sankey Diagramの作成
(ここから先は元記事に沿って下さい。画像が多くなってしまうので。)
まずPath Frame(bin)を置きます。このとき、右クリック→欠落した値を表示、します。
次に欠落した値も表示されているPath Frame(bin)を”詳細”に置きます。このときDimension等々も置いてください。
マークを”多角形”にして、”パス”にPath Indexを入れます。このとき、表計算は”次を使用して計算:Path Frame(bin)”で設定してください。Tを列に置きますが、表計算の設定は同様です。
Step 10.Sankeyポリゴンを行に置く
ここからは行シェルフに置いた”Sankey Polygons”の表計算の設定を正しくしてください、というだけです。元記事に沿って設定してください。
正しく設定できていれば、ちゃんとSankeyが出来ているはずです。
個人的に思う間違いポイントは、例えばDimension 1に関係するもの(MAX/MIN Position 1とか)の表計算の順番が、ちゃんとDimension1が上でDimension 2が下になっていない、とかでしょうか。
・最後に
データ加工のいらないSankey Diagram、いかがでしょうか。
計算式が大変ですが、これでお手軽に?Sankeyが使えます。やったぜ、という感じですね。