TableauでJoy Plotを作る


今回のテーマはJoy Plotです。下図(左)をJoy Plotと呼びます。

JOY DIVISIONという音楽グループによる「UNKNOWN PLEASURE」というアルバム画(右)に因むようです。

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

https://public.tableau.com/profile/yoshitaka6076#!/vizhome/BlogJoyPlotRefine/FluPatientNormalized?publish=yes

また以下を参考にしています。

https://www.kenflerlage.com/2018/05/joy-plot.html

異なるカテゴリーの数字推移などについて、推移の相関性などを見るのに適していると思います。近いのはエリアチャートですが、推移を被せて見ることができるので、より関係性を見やすいかなと。

2018年4月ごろに以下2つのJoy Plotの勉強ノートを執筆しましたが、その内容をRefineします。

How to Create the Joy Plot

How to Adjust Your Joy Plot: Let's Try Normalization

当時はこちらのブログを参考に作成しており、一方でまだ表計算に対して慣れていなかった自分は「INDEX()よくわからないし、パラメータ制御できる形で作ればいい」という、とてもメンテナンス性の低い方法でVizを作成していました(ディメンションに新しい項目が増えたら都度FIXしないといけない、各ポリゴンの並び替えがパラメータ制御、など)。

また、欠損値についても何も考えておらず、ちょっと実用性に欠ける方法でJoy Plotを使っていたので、今回は復習ということでJoy Plotを実装しやすい形で整理します。

【追記:上記の方法の方が計算は軽いかもしれない】

どうにも今回の方法だと、計算パフォーマンスが重くなる傾向がありました。比較的小さめのデータなら今回の方法は大丈夫ですが、そうでなければ上記のように行レベル計算を使って作ってあげるのも一考です。Vizを使う人のパソコンスペックとも相談ですね。

【データ準備と計算式用意】

Joy Plotには簡単なデータ前処理?をします。その結果データサイズを2倍にしますが、そこはTableau2018.3新機能の「正規化された抽出」が良い感じに輝いてくれそうですよね。

まず以下の簡単なテーブルを用意し(もしくはカスタムSQLでもOKだと思います)、以下のようにJOINします。

このJOINの必要性は後ほど説明します。ただSankey Diagramも前処理なしで出来るようになりましたし、これも頑張れば前処理なしで実はいけそうですよね。

今回は例題として、「サブカテゴリーごとの売上推移」をJoy Plotで作ることを目指します。

したがってJoy Plotに用いるDimensionとMeasure、またポリゴン用のDateとPathを下記のように設定しておきます。ここで[DATE RANGE]はDATETRUNC()の中身を変えるための、単なる文字列パラメータです。

Dimension

[Sub-Category]

Measure

[Sales]

Date

DATE(DATETRUNC([DATE RANGE], [Order Date]))

Path

IF [Primary/Zero]="Primary" THEN [Date] ELSE DATE((INT({FIXED [Dimension]: MAX([Date])})*2) - INT([Date]) + 1) END

Pathについて、まずは下記のGIFを見て頂いた方がわかりやすいかもしれません。


エリアチャートはポリゴン(多角形)で作成しています。エリアチャートの値は後程出てきますが「PrimaryならMeasureを返し、それ以外は0」をとります。このようなポリゴンを作成するために

・Dateに沿ったMeasureの値を出すために、まずはDateと同じ値をとり

・Dateの終点についた後は、そこからDateの日幅と同じ長さだけ追加で取る

ような、ある意味で横軸を「逆走する」Pathを用意する必要があります。

(正直なところ、どう説明したらいいか困るところがあるので、ぜひワークブックをダウンロードして遊んでみてください。)

【基本のJoy Plot】

ここからやっと本題に入ります。まず初めに、上記のPrimary/Zeroに沿ってMeasureと0を出しわける必要があるので、それ用の計算フィールドを作成します。

Measure Adjusted

SUM( CASE [Primary/Zero] WHEN "Primary" THEN ZN([Measure]) ELSE 0 END

)

次に、Dimensionに沿ってポリゴンが作成され、それぞれのポリゴンが基準位置を変えられるよう、次の計算式を作成します。

Measure Adjusted for Dimension

[Measure Adjusted] + (

MAX({FIXED:COUNTD([Dimension])})

- WINDOW_MAX([INDEX])

)

* [Spacing_NotNormalized]

ここで、[INDEX]はDimensionに沿ったINDEX()、[Spacing_NotNormalized]は数値型のパラメータです。

[Measure Adjusted]はMeasureもしくは0をとる計算フィールドでした。

2行目の+意向で、ある意味での切片を足してあげることにより、ポリゴンの始点を平行移動させています。

ここで

MAX({FIXED:COUNTD([Dimension])}) - WINDOW_MAX([INDEX])

についてですが、要は「Dimensionのあるカテゴリーが何番目か」の逆順、というだけです。ここでWINDOW_MAX()を使用している理由ですが、INDEXは欠損値があった場合にずれ、値が小さくなる可能性があるからです。

したがってWINDOW_MAXもしくはRUNNING_MAXで、Viz内の最大のINDEX値を各データ点で付与し、Joy Plotが崩れることを防いでいます。

以下にINDEXとWINDOW_MAX(INDEX)それぞれでの、Dateに沿った値を可視化しています。


前者は欠損値により値がばらつくのに対し、後者は一定の値をとり続けています。

これらを以下のように配置、設定すれば、下記のようになります(Order Dateのフィルターは簡単化のためです。意味は特にありません)。

この際、DateとPathに「欠落した値を表示」チェックを入れるようお願いします。


これで基本的なJoy Plotの作り方は以上です。

一方で「Measureの値スケールがDimensionの各項目で大きく異なる」ので、いくつかのポリゴンがかなり見にくくなっています。

もし「各項目の値よりも、各項目での関係性を見たい」という場合には、みにくいものが多くなってしますこの状態では、あまり便利ではないですよね。

ということで、それぞれのポリゴンのスケールを合わせる方法を以下にご紹介します。

【Joy Plotのスケールを合わせる:Normalizationの使用】

Normalizationについては以下を参照してください。話としては0~1へのスケーリングです。

データの正規化

以下の計算式を用意します。[Spacing_Normalized]は数値型のパラメータです。

Measure Adjusted Normalized

([Measure Adjusted] - WINDOW_MIN([Measure Adjusted])) / (WINDOW_MAX([Measure Adjusted]) - WINDOW_MIN([Measure Adjusted]))

Measure Adjusted for Dimension

[Measure Adjusted Normalized] + (

MAX({FIXED:COUNTD([Dimension])})

- WINDOW_MAX([INDEX])

)

* [Spacing_Normalized]

そして先ほどと同じように配置し、表計算を以下のように設定すれば完成です。

基本版とNormalized版を並べると、以下のようになります。

ちなみに、下位のチャートを上位のチャートに被せるように配置したい場合は、以下のようにマークの配置と表計算の設定をお願いします。

INDEXの設定とマークの設定が逆になること(並び順も含めて)がポイントです。


【別データでの例】

ここまで欠損値の話もありましたのでSuperStoreデータでやってきましたが、必ずしもJoy Plotでなくてもいいかなというデータかなと。

ということで、Joy Plotが輝きそうなデータでの例をお見せします。データはMakeover Monday 2018/W25: U.S. Influenza Surveillance Report から。

Normalized版では

・それぞれの世代での傾向の理解と、世代間の”傾向”の比較ができます。

・一方で実際の患者数は見えないので、その点は別で気に掛ける必要があります。

Non-Normalized版では

・それぞれの世代でのピークを見つけやすいです。

・どの世代が最も患者数が多いのか、一目でわかります。明らかに5-24歳が他のチャートに被っていて目立っています。

・一方で患者数の少ない世代はデータがちょっと見にくいです。65歳以上グループが辛いですね。

それぞれのバージョンでPros/Consありますが、どちらにしてもストーリーを伝えやすい形になっているのではないでしょうか。特にNormalized版は、傾向の異常値(2011~2012の患者数減少、もしくは2012年以降の患者数増加の傾向、また2017~2018年は急上昇していますね)が分かりやすいのではと思います。

Joy Plot、いかがだったでしょうか。

Tableauライフのアクセントとなれば幸いです。


© 2023 by Actor & Model. Proudly created with Wix.com