JOVANA
Explore Library Glossary Getting Started Three Levels Fields How it works Mission
Join the mission
All guides

誠實而清楚的圖表

同一份資料可以誤導、也可以啟發。截斷的座標軸、雙軸、糟糕的配色,以及讓圖表保持真實的資料墨水紀律。

圖表如何誤導(常常不是故意的)

想像兩位分析師拿到完全相同的數字:某公司的季營收,一年內從 400 萬美元成長到 412 萬美元。第一位畫出一張圖,會議室一片驚呼——營收看起來像翻了三倍。第二位畫出一張圖,大家卻只是聳聳肩——成長看起來很平。同一份資料,反應卻相反。兩位分析師都沒有改動任何一個數字,他們改的只是那張圖。

圖表是一種翻譯。它把數字轉成視覺記號——長條的長度、點的高度、一塊顏色——而我們的眼睛讀這些記號,比讀一張表格快得多。這份速度正是資料視覺化的全部重點:一張好圖能讓真相在一秒內跳出來。但同樣的速度也是危險所在。你做的每一個選擇——座標軸從哪裡開始、把哪兩條線放在同一塊畫布上、顏色代表什麼——都在讀者還來不及思考之前,悄悄地把結論推向某個方向。

安斯庫姆四重奏:四組資料的平均數、變異數與相關係數幾乎相同——形狀卻天差地別。對誠實圖表而言,這個教訓是「一定要先畫圖」的鏡像:正因為圖像承載了這麼多意義,你畫它的方式也就承載了同等的責任。

四張散布圖共用相同的摘要統計量,卻分別呈現一條乾淨的直線、一條曲線、一條被單一離群值拉歪的直線,以及一疊垂直點加上一個遠離的點。

在前面幾篇指南裡,你學到了為什麼一定要先畫圖,以及如何為你的問題挑對圖表。這篇指南談的是第三項技能:把那張圖畫得誠實。我們會逐一走過圖表誤導人的經典手法——截斷的座標軸、雙軸、隨便的配色——接著走過那套讓圖表既清楚又真實的正面紀律,一路到把多張圖表組合成一個儀表板。

截斷座標軸的把戲

讓我們把會議室那個故事變具體。某產品上個月賣了 100 件,這個月賣了 103 件——這是真實但不大的 3% 成長。你的主管希望這張投影片看起來像一場大勝。世界上最簡單的把戲,就是把長條圖縱軸的底部砍掉。不讓座標軸從 0 開始,而是從 98 開始。

看看長條會發生什麼事。在長條圖裡,一根長條的意義就是它的長度:讀者靠比較長度來比較數量。當座標軸從 0 開始,兩根長條分別高 100 與 103——幾乎一樣高,這就是真相。但把座標軸改成從 98 開始,被畫出來的部分就只剩 2 與 5 那麼高。現在第二根長條是第一根的兩倍半高。一個 3% 的變化,被重畫成看起來像 150% 的飛躍。

有一個簡單的方法可以替這種扭曲標上一個數字。統計學家 Edward Tufte 把它稱為「謊言係數」(lie factor):變化在圖中看起來有多大,除以變化在資料裡實際有多大。

\text{lie factor} = \dfrac{\text{size of change shown in the graphic}}{\text{size of change in the data}}

一張誠實的圖,謊言係數接近 1。遠大於 1 表示圖在誇大;遠小於 1 表示它在掩蓋一個真實的效果。

把我們的長條代入。圖中第二根長條比第一根高了 150%;資料只成長了 3%。謊言係數約為 150% ÷ 3% = 50。這張圖把變化誇大了大約五十倍。這不是四捨五入的小爭論——而是「普普通通」與「就這麼做吧」之間的差別。

import matplotlib.pyplot as plt

months = ['Last month', 'This month']
units  = [100, 103]

fig, ax = plt.subplots()
ax.bar(months, units)
ax.set_ylim(0, None)        # force the bar axis to start at zero
ax.set_ylabel('Units sold')
plt.show()
一行誠實的程式碼:用 set_ylim(0, …) 強制長條的座標軸從 0 開始,而不是讓繪圖套件自動放大去「把畫面塞滿」。
  1. 長條與面積:數值軸永遠從 0 開始——它們的長度就是訊息。
  2. 折線與散點:可以用非零基線,但要標明範圍,且不要只為了放大一個小波動而裁切。
  3. 對你希望讀者並排比較的多張圖,維持同一套一致的刻度。
  4. 絕不要在沒有醒目視覺標記與註記的情況下,反轉或中斷座標軸(在刻度上藏一個斷口)。

截斷與中斷的座標軸是圖表說謊最常見的單一手法,正因為它感覺只是無害地「放大一下」。每當你看到一張戲劇性的長條圖,第一件要檢查的事,就是座標軸從哪裡開始。

雙軸與虛假的相關

這裡有另一個把戲,而這個連畫圖的人自己都會被騙。某個夏天,兩件事一起上升:冰淇淋的銷量,以及海灘上溺水的人數。把兩者放在同一張折線圖上——冰淇淋用左邊的縱軸、溺水用右邊的縱軸——兩條線幾乎完美地同步攀升。這張圖在悄悄說一個故事:冰淇淋很危險。

當然不是。有第三件事——炎熱的天氣——同時推動了兩者:高溫讓人去買冰淇淋、也讓人去海裡游泳,而有些人因此溺水。天氣是一個干擾因子(confounder),是躲在兩條線背後的共同原因。這張圖根本沒有測量任何因果連結;它只是把兩條同樣帶有夏天形狀的曲線並排放在一起。

那份自由正是雙軸真正的問題所在。因為左右兩條刻度互不相關,你可以把其中一條往上或往下滑,直到兩條線重疊,而讀者完全看不出你動過手腳。誠實的替代方案幾乎總是存在。如果兩組數列共用單位,就把它們畫在同一條共用座標軸上。如果不共用,就畫成兩張上下堆疊、共用同一條時間軸的圖——一對小倍數圖——讓讀者比較的是形狀,而不是你任意的縮放。

一個相關的誠實問題,是刻度本身。當一個量橫跨極大的範圍時——城市人口從一千到兩千萬,或不同網頁的造訪次數——一條普通的線性座標軸會把小數值壓到貼地,只有那些巨人看得見。對數刻度——每一格是相乘而非相加——能公平地呈現整個範圍。但對數刻度也容易被讀錯,所以一定要標明它是對數的,並記住此時相等的視覺距離代表的是相等的比例,而不是相等的數量。

在挑刻度之前,先看資料的分配。許多真實世界的量都是右偏的——有一條由大數值構成的長尾——直方圖能讓這一點一目了然;正是這種形狀,才讓對數刻度派得上用場。

以直方圖呈現的數種分配形狀:對稱的鐘形、向右拖出長尾的右偏分配,以及平坦的均勻帶。

色彩:色相、色階與色盲

色彩是製圖中最常被濫用的通道,部分原因是它太容易加上去、又太誘人讓人想把圖弄得「漂亮」。誠實使用它的第一步,是知道色彩有三種不同的工作,而每一種都需要不同類型的色階

  1. 類別型(質性):為無序的群組指定彼此分明的色相——紅、藍、綠代表三條產品線。只用少數幾個;超過大約七個,顏色就會糊成一團。
  2. 順序型:用同一色相由淺到深,表示有序的大小——由淡到深的藍代表降雨量由低到高。
  3. 發散型:兩種色相在一個有意義的中點相會——藍經白到紅,代表低於、等於、高於某個目標。

一個常見錯誤,是把彩虹(「jet」)色階用在有序資料上。它看起來很鮮豔,但我們的眼睛並不會把它的顏色感知成等距,於是它會在資料平滑之處憑空造出尖銳的邊界,又在別處藏起真正的跳變。感知上均勻的色階——viridis 是最有名的一個——能解決這點:資料裡相等的一步,看起來就是色彩上相等的一步。

接著是你觀眾的眼睛。大約每 12 位男性(與每 200 位女性)就有一位有某種紅綠色盲。如果你那條「上升」線與「下降」線之間唯一的差別就是紅與綠,那麼相當大一部分讀者看到的,是兩條一模一樣的灰線。解方是冗餘:絕不要讓色彩成為意義的唯一承載者。加上直接標籤、不同的形狀或虛線樣式,或用位置區分,讓這張圖即使變成灰階也依然成立。

import seaborn as sns

# A palette designed to stay distinguishable for color-blind readers
sns.set_palette('colorblind')

# Belt and braces: also vary the marker shape, not just the color
sns.scatterplot(data=df, x='price', y='sales',
                hue='region', style='region')
一次兩道保險:色盲友善的調色盤,再加上 style='region',讓每一組同時擁有自己的標記形狀——即使在灰階下,意義依然存在。

色彩只是視覺編碼的其中一個通道;位置與長度被讀得更準確,所以把色彩留給次要的區分,讓位置承載主要的比較。

資料墨水比:刪繁就簡以彰顯

一旦一張圖是準確的,下一項工作就是讓它清楚——而清楚通常來自刪減,而非添加。Edward Tufte 把這個概念命名為「資料墨水比」(data-ink ratio):一張圖裡所有的墨水(或像素)當中,真正在呈現資料的,相對於裝飾的,佔多少比例?

\text{data-ink ratio} = \dfrac{\text{ink used to show the data}}{\text{total ink in the chart}}

在合理範圍內,把這個比例推向 1。每一滴沒有承載資訊的墨水,都是對讀者注意力的一筆小稅。

Tufte 所稱的「圖表垃圾」(chartjunk)無處不在:粗重的格線、每根長條外圍的深色框、陰影、會傾斜並扭曲我們正想比較的那些長度的偽 3D 效果、多餘的圖例,還有花俏的背景。這些都不增加資訊;卻全都在跟資料爭奪讀者的目光。

  1. 刪除 3D、陰影與漸層——它們會扭曲長度,又毫無作用。
  2. 把格線調淡或移除;若要保留,就讓它們成為資料後方的淡灰色。
  3. 當你能在圖上直接標註各數列時,就拿掉圖例。
  4. 除非順序本身有意義,否則依數值(而非筆畫或字母)排序類別。
  5. 把標籤上的數字四捨五入到讀者實際用得上的精度。

這一切背後的紀律,就是資料墨水比:拿不定主意時,就拿掉一樣東西,看看訊息是否變得更清楚。

引導視線的標註與註解

一張乾淨又準確的圖,如果讀者得用猜的才知道它在講什麼,依然是失敗的。視覺化中最被低估的工具,就是放在圖上的白話文字。從標題開始。像「營收」這樣的標題,浪費了螢幕上最有價值的一行字。一個直接點出結論的標題——「第四季營收成長 3%,是今年成長最慢的一季」——誠實而開門見山地告訴讀者該看什麼、以及你下了什麼結論。

其次,優先使用直接標籤,而非圖例。圖例會逼讀者的視線在色彩對照表與線條之間來回彈跳,還要在腦中記住一份顏色對名稱的對照。把每條線的名稱寫在它的右端,就完全省去了這份工。同樣地,替座標軸標上單位——「營收(百萬美元)」,而不只是「營收」——因為一個沒有單位的數字,還稱不上是資訊。

最後,替那件最重要的事加上註解。如果某條線在你改價的那一週飆升,就在那裡直接畫一個小註記:「3 月 3 日漲價」。註解正是你這位分析師引導讀者視線到重點之處——把話講明白,比期待他們自己注意到更誠實,也遠比重畫座標軸去強迫他們注意更誠實。

從單張圖表到儀表板

儀表板不過是把許多圖表放在同一個螢幕上、用來持續追蹤的東西——但「許多圖表」會把這篇指南裡的每個習慣放大,無論好壞。它的組織原則是每張圖回答一個問題。每一格都應該回答一個單一、清楚的問題——「這週有多少人註冊?」、「結帳錯誤率有沒有在範圍內?」——如果你說不出某張圖回答的是什麼問題,它就不該出現在儀表板上。

組一個儀表板,就是一次又一次地為每個問題挑對圖表:比較用長條、趨勢用折線、關係用散布、分配用直方圖。讓意圖對上圖表類型,本身就是一種誠實。

一張決策地圖,從你想回答的問題——比較、趨勢、關係、分配、組成——對應到適合它的圖表類型。

  1. 把最重要的那張圖放在左上角,也就是視線最先落下的地方。
  2. 在每一格中,對同一個指標使用相同的刻度與相同的顏色。
  3. 呈現脈絡:一條目標線、上一期,或正常範圍,讓一個數字有意義。
  4. 抵抗無止盡的擴張——一個沒人能一眼看懂的儀表板,只是一面數字牆。

這就是誠實而清楚的圖表的全部紀律。讓資料來決定座標軸,尤其是長條圖那條歸零的基線。對雙軸保持高度懷疑,絕不要把兩條對齊的曲線讀成因果。用那三種誠實的方式使用色彩,並讓圖表在灰階下也能成立。把墨水花在資料上,而非裝飾上——但保留有幫助的脈絡。在標題裡說出結論、直接標註、替重點加上註解。圖表是用墨水構成的論證;這篇指南,就是教你如何讓這份論證既有說服力、又是真的。

最後一個習慣,把整個視覺化主題串起來:那些能說服觀眾的圖,是從你畫給自己看的那些雜亂的圖長出來的。先畫圖以理解——探索性資料分析——才讓你有資格畫出一張有把握、誠實的最終圖表。為你自己的眼睛畫上一百張粗略的圖;再把其中最清楚說出真相的那兩張,打磨乾淨。