Seaborn¶
想像主管交給你一份 Excel,裡面有幾百筆顧客、訂單或學員紀錄,然後問:
- 哪一群人的表現最好?
- 成績不好,是不是因為通勤太久或手機用太多?
- 哪種飲料最受歡迎,應該多準備哪一種?
- 哪一組的資料差異最大,平均值會不會騙人?
- 我要在三分鐘內報告,怎樣讓主管一眼看懂?
只把 DataFrame 印出來,人腦很難一次比較數十列數字。圖表的工作,就是把「數字之間的關係」翻譯成人類容易理解的形狀、位置與顏色。
三個套件如何分工?¶
| 套件 | 生活比喻 | 本課工作 |
|---|---|---|
| pandas | 整理資料的試算表高手 | 讀 CSV、篩選、分組、計算 |
| Matplotlib | 畫布與畫筆 | 建立畫布、標題、座標軸、儲存圖片 |
| Seaborn | 懂統計與配色的設計師 | 用少量程式碼畫美觀的統計圖 |
Seaborn 建立在 Matplotlib 上。因此常見寫法是 Seaborn 負責主要圖形,Matplotlib 負責標題、尺寸與輸出。
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
# `sns` 與 `plt` 只是社群慣用縮寫,不是 Python 規定。
先分清楚兩大資料型態¶
數值型資料可以做加減與平均,例如通勤分鐘、睡眠小時、測驗分數。類別型資料是名稱或群組,例如班別、居住地、是否取得證照。編號雖然由數字組成,卻只是識別名稱,計算「平均編號」沒有意義。
| 問題 | X | Y | 建議圖表 |
|---|---|---|---|
| 哪種飲料人數最多? | 一個類別 | 無 | countplot |
| 三班平均成績誰較高? | 類別 | 數值 | barplot |
| 手機時間集中在哪? | 一個數值 | 無 | histplot |
| 自習與成績有關嗎? | 數值 | 數值 | scatterplot |
| 各通勤方式差異大嗎? | 類別 | 數值分布 | boxplot |
| 多個數值誰和誰較相關? | 多個數值 | 多個數值 | heatmap |
資料讀取與健檢¶
import pandas as pd
df = pd.read_csv("Seaborn_datasets/職訓生活與學習紀錄.csv")
print(df.shape) # (72, 16):72 列、16 欄
print(df.head()) # 前五筆
print(df.info()) # 欄位、資料型態、非空值數量
print(df.isna().sum()) # 各欄缺值數
print(df.describe()) # 數值欄的統計摘要
Seaborn 的共同語法¶
sns.scatterplot(
data=df, # 資料從哪張表來。
x="每週自習小時", # 水平方向放哪個欄位。
y="課後測驗", # 垂直方向放哪個欄位。
hue="組別", # 依某欄位改變顏色,多呈現一層資訊。
# `style`:依類別改變點的形狀。
# `size`:依數值改變點的大小。
# `palette`:選擇配色。
# `order`:指定類別順序,而不是接受預設順序。
)
# 這種把資料欄位對應到視覺特徵的做法,叫做 visual encoding。位置通常最容易精準比較,其次是長度;面積與顏色較適合輔助,不適合塞太多資訊。
axes-level 與 figure-level¶
這是新手常卡住的地方:
scatterplot、histplot、boxplot等 axes-level 函式,畫在某一個座標軸ax上,適合plt.subplots()組合儀表板。relplot、displot、catplot、lmplot、pairplot等 figure-level 函式,會自己管理整張圖,方便用row、col拆分面板。
figure-level 函式回傳的通常不是 Axes,而是 FacetGrid 或 PairGrid。所以設定總標題常寫:
類別資料:countplot 與 barplot¶
countplot:數一數有幾筆¶
countplot 不需要先算人數,它會直接計算每個類別出現幾次。適合回答人氣、件數、訂單數、缺陷數等問題。
barplot:先統計,再畫柱子¶
barplot 的每根柱子預設代表該組 y 的平均值,不是資料筆數。這是它與 countplot 最大的差別。
預設可能出現誤差線,它表示估計值的不確定程度,不是裝飾。如果課程初期只想專注平均值,可用 errorbar=None;正式分析則應說明是否顯示信賴區間。
課堂陷阱題:柱子最高的班是否代表每位學生都比較高?不一定。平均值會隱藏個別差異,下一節的箱型圖會補足這個問題。
數值分布:histplot 與 kdeplot¶
直方圖會把連續數值切成數個區間,再計算每個區間有幾筆。它和長條圖看似相同,但意義不同:
- 長條圖的 X 軸是獨立類別,順序未必有距離意義。
- 直方圖的 X 軸是連續數值,柱子相鄰,區間有固定範圍。
bins=10 就像把考卷依分數放進十個箱子。箱子太少會抹掉細節,太多則會顯得零碎,因此應試不同 bins,確認結論是否穩定。
KDE 是平滑的密度估計線,可以想像在每個觀察值上堆一小座土丘,再把所有土丘疊加。它適合觀察形狀,但線高不是人數,且可能在不合理範圍延伸,所以不能盲信。
散佈圖:兩個數值的關係¶
每一個點代表一位學員。點的水平位置是自習時間,垂直位置是課後成績。如果點群大致由左下往右上,稱為正向關係;由左上往右下是負向關係;像一團雲則可能沒有明顯線性關係。
迴歸圖:用一條線摘要趨勢¶
regplot 在單一座標軸畫散佈點與迴歸線;lmplot 能用 col 或 row 分面。迴歸線不是把所有點連起來,而是尋找一條能概括整體關係的線。
線周圍的半透明帶通常是信賴區間:根據現有樣本,估計趨勢線可能落在哪個範圍。樣本少或資料分散時通常較寬。它不是「95% 的點都會在帶內」。
注意:直線只摘要線性趨勢。若資料明顯呈 U 形,一條平坦的直線可能錯誤暗示沒有關係。
箱型圖與小提琴圖:平均值之外的故事¶
先把數字排序,四分位數把資料切成四等份:
- Q1:25% 的資料在它以下。
- 中位數 Q2:一半在下、一半在上。
- Q3:75% 的資料在它以下。
- IQR = Q3 - Q1:中間 50% 資料的跨度。
箱型圖的箱子從 Q1 到 Q3,箱內線是中位數。鬚通常延伸到 Q1−1.5×IQR 與 Q3+1.5×IQR 範圍內的最遠資料,外側點是值得檢查的潛在離群值。
離群值不是錯誤值。通勤 90 分鐘可能是真實情況,若直接刪掉,可能正好刪除最需要遠距協助的學員。正確流程是回頭核對,再決定保留、修正或排除並留下說明。
小提琴圖的寬度代表該位置附近的資料密度,能看到箱型圖看不到的多峰形狀;但資料太少時,平滑外形可能讓人誤判。
pairplot:一次探索多個欄位¶
pairplot 會產生矩陣:對角線顯示每個變數自身的分布,其他格顯示兩欄之間的散佈關係。它適合探索階段快速找線索,不適合直接塞進簡報,因為欄位一多會變得巨大。
若放入 10 個數值欄位,最多會形成 10×10 個格子。先依問題挑選 3~5 個重要欄位,通常更容易閱讀。
相關係數與熱圖¶
Pearson 相關係數介於 -1 到 1:
- 接近 1:強正向線性關係。
- 接近 -1:強負向線性關係。
- 接近 0:沒有明顯線性關係。
正負號表示方向,絕對值表示線性關係強弱。不要機械式宣稱 0.7 以上就一定重要;不同領域、樣本數與風險情境的判準不同。
numeric_df = df.select_dtypes(include="number")
correlation = numeric_df.corr()
sns.heatmap(correlation, annot=True, cmap="RdBu_r", center=0)
熱圖只是用顏色顯示數值矩陣,本身沒有創造新的統計結果。一定要搭配格內數字、色條與清楚標題,並記住:
- 相關不等於因果。
- 離群值可能大幅改變相關係數。
- 接近 0 仍可能有曲線關係。
-
同一資料重複看很多關係,可能偶然找到看似很強的結果。
分面圖:把人群拆開比較¶
整體資料可能看不出差別,但分班後才發現各班模式不同。分面圖讓每個子群使用相同座標尺度與圖形規則,方便公平比較。
分面過多會產生「郵票牆」。若地區有十幾種,應先合併、篩選,或改用互動式工具。
美化不是裝飾,是降低閱讀成本¶
主題與情境大小¶
sns.set_theme(style="whitegrid", context="notebook")
# - `style="whitegrid"`:水平格線幫助比較數值。
# - `context="talk"`:簡報字體較大。
# - `context="paper"`:報告用字體較緊湊。
好顏色的原則¶
- 類別:用色相不同的離散色盤,如
Set2。 - 低到高:用單向漸層,如
Blues。 - 負到正:用雙向色盤,如
RdBu_r,並設center=0。 - 同一類別在所有圖中盡量使用同一顏色。
- 不只靠紅綠區分,兼顧色覺差異使用者。