上週做投影片,把 SPSS 的長條圖直接複製貼上去,螢幕上很好看:三種班別用三種顏色分得清清楚楚。前天把口試要交的紙本印出來,系辦影印機只能印黑白。三根柱子變成三種深淺很接近的灰,最左邊跟最右邊幾乎分不出來。
我原本以為這是「印表機的問題」,後來才知道不是。這篇要做的圖表工具,核心不是配色好不好看,是確保同一張圖在螢幕上、彩色列印、黑白影印三種情況下,都還分得出來。中間會有一個我自己也沒想到的結果。
「色盲安全」不等於「黑白安全」
網路上搜得到的「色盲友善色票」,多半是為了色覺辨認障礙的讀者設計的——避開紅綠這種對某些色盲最難分辨的組合。這件事做對了,但它解決的是「色相」的問題,沒有處理「亮度」的問題。
黑白影印機做的事,是把每個顏色換算成一個灰階亮度值,色相全部丟掉。如果兩個顏色色相不同、但亮度剛好接近,色盲安全色票一樣會在黑白影印時變成兩塊很像的灰。這件事色票本身不會告訴你,要自己算。
亮度的算法有公式,人眼對綠色最敏感、對藍色最不敏感,所以不是把 RGB 平均起來,是加權平均:
亮度 = 0.2126×紅 + 0.7152×綠 + 0.0722×藍
這個公式我不用背,讓工具算,但我要知道它在算什麼,不然出來的數字我沒辦法判斷合不合理。
先寫規格檔
跟前面每個工具一樣,analysis/figure-style.md:
SKILL.md 全文
存在 .claude/skills/figure-apa/SKILL.md:
清理後的資料檔,使用者指定要畫哪個變項、用什麼圖型
#E69F00(橙):相對亮度 0.638
#56B4E9(天藍):相對亮度 0.643
#009E73(藍綠):相對亮度 0.476
最小亮度差:0.005(建議 > 0.15)
橙色和天藍色,看起來是完全不同的兩種顏色,換算成灰階之後亮度只差 0.005,幾乎是同一個灰。這兩個顏色都是教科書等級的「色盲安全」推薦色,但沒有人告訴我它們黑白印出來會疊在一起。
換掉天藍,改用藍、紅紫、黃這三色:
#0072B2(藍):相對亮度 0.370
#CC79A7(紅紫):相對亮度 0.557
#F0E442(黃):相對亮度 0.858
最小亮度差:0.187(建議 > 0.15,通過)
這組通過了。重跑一次,圖表存出來,我自己拿灰階版看了一眼:深灰、中灰、淺灰,三根柱子分得很清楚,加上斜線、交叉線、點狀三種圖樣,就算完全看不到顏色也分得出來是哪一組。
實際跑出來的圖
用清理好的資料畫「不同班別的職業倦怠總分」:
班別 n M SD
白班 87 64.85 6.65
小夜班 90 65.83 7.20
大夜班 102 65.72 6.82
彩色版三根柱子是藍色斜線、紅紫色交叉線、黃色點狀,中文標題和座標軸標籤正常顯示,沒有變成方框。灰階版轉出來,深灰、中灰、淺灰配上不同圖樣,肉眼可以清楚分辨。
這裡要老實說一句:這張圖的倦怠總分是我在這支腳本裡自己加總 22 題算出來的,跟 Day 15 說的「加總量表分數還是在 SPSS 裡手動算」是兩條平行線——畫圖用的加總分還沒有拿去跟 SPSS 算出來的版本對過一次。這件事我列進今天的待辦,論文正式的表格和統計,數字要以 SPSS 那邊為準,這裡只是為了畫圖先自己算一份。
哪裡會出錯
中文字型不設定,圖表上的字會變成一格一格的方框。 matplotlib 預設字型不含中文字符,第一次畫圖title 和座標軸的中文全部變成豆腐塊。解法是在畫圖之前指定 Microsoft JhengHei,Windows 內建就有這套字型,不用另外裝。這個坑幾乎每個第一次用 Python 畫中文圖表的人都會踩到一次。
色盲安全色票裡的顏色,兩兩之間不保證灰階夠分得開。 這是今天最大的發現,上面整節都在講。教訓是:色票只解決色相,亮度要自己另外算,不能因為色票的名字裡有「安全」兩個字就放心。
螢幕預覽跟印出來的解析度不一樣。 matplotlib 預設存圖是 100 dpi,螢幕上看起來清楚,印在紙上邊緣會有點糊,字看起來毛毛的。存圖時明確指定 dpi=300,印出來才會跟螢幕上一樣銳利。這個坑不會馬上發現,因為多數人是在螢幕上檢查圖表,直到真正印出來交出去才會看到差別。
只靠顏色,沒有第二種區分依據,還是有風險。 就算亮度差通過門檻,我還是每個類別都配了不同的 hatch 圖樣,這是保險而不是多餘——亮度門檻是我自己抓的經驗值,不是精確的科學保證,兩種區分方式疊在一起,才不會因為一次疏忽就讓圖表在某種輸出情境下失效。
這件事跟資料清理是同一種邏輯
Day 14 說錯誤不會報錯,Day 16 說遺漏值代碼設對了不代表每個下游程式都記得排除它。今天這件事是同一個原則在圖表上的版本:「看起來對」在一種情境下成立,不代表在另一種情境下也成立。 螢幕上看起來完美的配色,黑白影印可能失敗;我自己核對的時候如果只看螢幕,永遠不會發現這個問題。所以規格檔裡才會寫「輸出灰階版本供人眼複查」——這一步不是多做的,是唯一能抓到這種錯誤的方法。
我還不確定的地方
0.15 這個亮度差門檻是我自己抓的,還沒有找到護理或社會科學領域對這件事的具體建議,可能太保守也可能不夠。另外圖表用的加總分還沒跟 SPSS 核對過,這件事我列進下週的待辦,在真正把圖表放進論文之前一定要做。
明天
Day 18:我曾經在原始問卷檔案上直接動手改,三個月後想回頭才發現沒有回頭的選項——那次的完整經過,以及它怎麼變成 Day 4 那條「不要動 data/raw/」的規則。