利用 Tableau 繪製桑基圖(1):入門
在處理資料時
有時候會希望呈現兩個分組之間的流向或流量
一般是稱為桑基圖(Sankey diagram)
也有人稱之為能流圖
相關的介紹網路上有蠻多應用的說明
也有許多軟體能夠繪製這樣的東西
而從這篇開始
會希望很淺顯的介紹怎麼利用Tableau這套軟體來製作
這篇先從基本的概念先說明
主要在於怎麼畫出那些曲線
所以在資料左、右方的寬度設定上是先用偷吃步的方式
之後別篇會再更進一步說明一些進階的作法
※這邊也要特別感謝好友丞倫以及神人ML
Tableau基本操作都是跟他們學的~
在想要嘗試畫桑基圖之前也有先問一下丞倫說會不會很難
他說:「那些人真的很閒,竟然可以想出那樣的作法。」
這也就代表一定是有一些相當神奇的製作方式
有這個提示之後也就知道網路上找到的教學應該也有得研究了
後來是找到了 這個影片 和 這個影片
他們是有分別利用不同的方式來做資料的前處理
算是比較進階的作法 (像是有利用到資料庫的方式)
我覺得也蠻值得看的!
先簡單講一下Tableau畫這種圖的概念
其實他並不是完全的流線
而是用切得很細的直線接起來
肉眼看起來就好像是滑順的流線這樣
所以如果把線不要切那麼細的話
就會發現實際上是這種一段一段的直線把各個點接起來
從左邊到右邊
這些中間每一個節點都應該是一筆資料
所以假設我們原本可能左邊有30筆資料好了
但實際上我們會需要把這30筆複製好多次
讓這30筆資料要呈現為30條連線
每條連線中間的接點(如圖中所示黑圈處)
在橫軸不同的位置有不同的高度變化
而最後一個點的高度就會剛好等於流線的終點位置這樣
基本概念大概就是如此
所以問題就在於我們要怎麼決定這些中間點、一直到最後終點的位置怎麼設定
下面我們就一樣用個很簡單易懂的範例資料吧!
身為阿湯哥影迷
這次示範的資料就用阿湯哥演出的電影資料!
阿湯哥主要從1983年的《保送入學》這部片開始有名氣
(當年21歲也因《保送入學》被提名金球獎最佳男主角)
後來一路演了許多不同類型的電影
雖然近年大家比較熟悉的都是他的諜報動作片
不過他有演過許多如喜劇、戰爭、愛情、運動等多樣化的題材
想要把他選不同類型的片子
來對應到不同的片商
順便再呈現電影票房的流量這樣
如下表,資料先在excel中處理:
前處理可以先把片型 (也就是桑基圖的左邊起頭) 先排序
然後增加一欄「左順序」
(算是直接偷吃步的方式,有其他進階作法以後再介紹)
目前簡單作法就是直接照順序列下去、先不管寬度
只是不同的片型中間希望要有一點分隔
所以第一格先打1
第二格開始就直接用excel的公式
讓它直接判斷不同片型的就隔3,否則就隔1
順序的位置完成
這邊就是桑基圖左方各筆資料的順序
別忘了完成後要把那整排複製
重新貼上純數值
(也就是把公式去掉~不然之後換別的方式排序公式會亂掉)
再來是片商的順序值
也就是流線右邊終點處的位置的值
一樣在這篇先用偷吃步的簡單方法
把片商排序後的順序值
一樣把同片商的就繼續加1、不同片廠就隔3這樣
設定順序數值完成
這就是右邊終點的位置
再來就是要設定流線中間那些點了
不過我們當然不用手動的一再複製
這邊就可以使用Tableau的聯集功能~
然後之後設定各個中間點的座標也都可以直接在Tableau裡面做
所以目前步驟就是希望能夠直接讓每一個原本的資料
都可以直接複製個好幾次
以因應之後設定流線的中間點
首先
增加一欄叫做「連接用」
裡面的值就直接用「LINK」字串吧
然後開一個新的Sheet (可以隨自己喜歡取名~不影響)
增加兩個欄位
一個叫「連接用」
另一個叫「橫軸」
所謂橫軸
就是我們之後要切割一小段一小段的中間點的橫軸座標
那當然是切得細一點
看起來比較流線、滑順
而根據前人的嘗試
發現橫軸每段切 0.25
看起來就很順
而不會一段一段卡卡的
然後再來就是我們想要做出曲線的效果了
這邊我們可以用「S曲線」
它英文叫做「Sigmoid」
大概長這樣:
這是一個從趨近0到趨近1的曲線
而從圖中可以看到它大概從 -6 到 6 這個範圍
這一段是最像我們想要的樣子
所以我們想要的座標橫軸
就是從 -6 到 6
然後每0.25切一段
再來就是如下方這樣
橫軸那個欄位就直接從-6, -5.75, -5.5, ... 一直到6
一共會有49筆
然後左邊連接用那欄就一律都使用「LINK」
跟我們剛剛原本那個Sheet的「連接用」欄位叫一樣的名字
再來就沒excel的事了
準備打開Tableau
直接用它的功能來
來從原本的資料
複製產出許多中間點以及終點的各筆資料
在Data Source中
將「片單」與「連接」這兩個Sheet都拉進來
然後因為Tableau會將兩個Sheet中的「連接用」裡面的LINK直接交集
並直接幫我們把原始的每一筆資料都變成49筆
各筆的「橫軸」值則分別從-6, -5.75, -5.5, ... 一直到6
大概就是這樣子的概念:
所以剛剛做的就是幫我們把每一條線的49個點的「橫軸」座標都先做好了
不用自己手動搞老半天
那再來就是縱軸的值了
就好像上圖的y1、y2...要怎麼去算出來呢?
我們先進到 Tableau 的 Sheet 1 吧
左邊的資料可以看到有Dimensions跟Measures
分別是離散的資料與連續型的資料
在最下面空白處這邊右鍵
選擇「Create Calculated Field...」
這邊我們要先計算出對應於各個不同橫軸座標的y值
這邊要用兩個步驟
首先我們要先算出各橫軸座標的「原始Sigmoid值」
再根據各筆資料來做上下比例的壓縮與位移 (如下圖)
這樣就能根據頭尾的位置
再在中間畫出各個點了
首先
Sigmoid函數長這樣
wiki也有公式
其中在指數上面那個 t
就是橫軸的值
在我們剛剛「Create Calculated Field...」之後
就可以在上方輸入新的變數名稱
以及它的計算公式
這邊我們就是單純要求出原始的Sigmoid值
因此公式就照著上方那個公式來輸入:
EXP() 函式是Tableau內建的尤拉數函式
^則是次方符號
好了之後
我們就要再新增一個「畫曲線」的數值
也就是調整比例與位移之後的值
輸入如下:
這邊的計算的概念其實不會很複雜
中間的 ([右順序] - [左順序]) 就是上下縮放的比例
把它乘上原始sigmoid值
左邊再加上 [左順序] 來位移
或者也可以這麼想:
當橫軸從左到右
最左邊y座標是[左順序]
最右邊y座標是[右順序]
所以會有一個函式是:
[左順序] + ([右順序] - [左順序])*某個介於0~1的值
只要確保後面被乘的那個從左到右剛好是0~1就ok
總之這邊就大概是數學函式位移與縮放的邏輯思考
可能會需要想一下
想通了應該也就知道這邊的計算是要做什麼了
再來就是把 [橫軸] 拉到Columns裡面
按旁邊的鍵跑出下拉選單
然後改成Dimension
然後把 [畫曲線] 拉到Rows裡面
就會發現目前的是全部所有資料的總和形成的曲線
我們想要讓它各自分開
一條線是一部片的資料就好
所以接著就把各個單一資料拉到Detail
比方中文片名、英文片名
應該就可以發現出現一堆曲線了
(片型、片商可以不用拉到Detail~)
片型則可以拉到Color讓線條按片型有不同的顏色
初始產生的線大概這樣
已經有基本雛形出來了
再來就是先改自己喜歡的顏色
先點選Color
跳出的對話框裡面點選Edit Colors
然後就隨自己喜號將各個類別選擇顏色吧
右邊有很多可以挑選的色票可以慢慢挑
然後因為目前左邊顯示的順序上到下是由大到小
我們希望是由小到大 (就跟我們剛開始在excel裡面照順序那樣)
所以就要在座標軸上右鍵→Edit Axis
點選中間的Reversed
然後就可以把座標軸藏起來了
一樣右鍵
把Show Header取消就可以
底部的座標軸我們也要先處理一個東西
先右鍵→Edit Axis
把座標的區間改成從 -6 到 6
這樣線的邊緣就會切成平整而不會是圓頭
畫面會更乾淨俐落
設定好了之後就可以藏起來
然後畫面上方的Title也可以藏起來
然後想要再根據各部片的票房呈現粗細不同的話
也可以把票房變數拉到Size裡面
並且可以點一下Size調整粗細美觀
完成後大概可以長這樣
好像已經蠻有型了
可以看到阿湯哥演出的不同片型對應到不同片商
然後票房哪些是大賺的這樣
看來最多部也最賺的就是派拉蒙
蠻多都是特務片 (其實也就是不可能的任務系列)
阿湯哥演的科幻片也都還蠻賺的
入門的部份就先到這邊告一段落
之後就再介紹更進階的部份包括各線段的位置順序調整、以及在Dashboard中呈現及互動性等等
下面則是補充一些有的沒的亂玩:
【補充一】
在前面有介紹曲線的概念
基本上就是讓
[左順序] + ([右順序] - [左順序]) * 某個介於0~1的值
這個函式後面乘上的東西是某個0~1的函式就好
所以照這樣子來做
我們就不一定要用Sigmoid函數
而可以改成用其他的函數來玩玩看
比方用拋物線來呈現看看~
第一種是從平緩逐漸加劇的拋物線 (頂點在最左邊)
然後因為原本座標就 -6 到 6 懶得改了
就只要最左邊當橫軸=-6時 y值是0
然後最右邊當橫軸=6時 y值是1就好
那方程式就很簡單了:
畫曲線就一樣乘上去即可
其他步驟基本上差不多
拉出來後就會發現成功呈現了:
反過來說
如果希望改成是趨緩的拋物線
也就是頂點在右邊的拋物線
這就要稍微小改一下
因為是平方的關係會變成是1到0
所以後面要減1
讓它變成0到-1
畫曲線的部份就變成要用減的
完成:
不過拋物線的缺點就在於比較斜的那邊的邊緣會醜醜的
也不是那麼好觀察各組之間的區隔
所以也就沒有Sigmoid那麼好囉
但這時就會想到
跟Sigmoid的長像有點像的
不就是Sin函數嗎?
所以也可以來試試看
剛好Tableau也很強大的準備了SIN()函式和PI()函式
我們想要的Sin的曲線是從谷底到峰頂
它需要的是從 -π/2 ~ π/2
所以當橫軸是-6 到 6 時
就直接除以12 再乘上 PI()就好了
而Sin位移之後仍然是-1到1
所以要再加1
讓它變成 0 到 2
然後再除以2
這樣就確保最後出來要乘上去的值一樣是 0 到 1
可以比較一下
這是用Sigmoid函數的圖:
這是用Sin的圖
我覺得都算是蠻不錯的!
就看個人喜好囉
當然如果是想要用Sin來畫的話
在最初excel時也不一定非得從-6到6
另外如前面有提到的
之所以Sigmoid會從-6 到 6
也是因為它的圖大概頭跟尾是趨於平緩的
而且也剛好切割成49段
視覺上也是很滑順
不然其實Sigmoid值在-5跟5時就已經很接近1了
【補充2】
另外想要知道為什麼說Tableau畫這個的作法是一小段一小段接起來
這邊也可以做個小實驗
就是不要切那麼密
在最初Excel裡面就可以先試試隔1.5切
如下:
這樣畫出來的圖就可以明顯看出是各點之間的連線了:
.
.
.
.
.