Day 21 Seaborn 統計圖表
引言
Day 20 我們學會用 Matplotlib 畫出折線圖、長條圖、散佈圖,已經能處理大部分的圖表需求。但當資料量變大、需要同時呈現「分佈」、「相關性」、「類別比較」這類統計主題時,Matplotlib 的程式碼會變得冗長,圖表的配色也常常不夠理想。這時候,與其每次都自己慢慢調整,不如交給專門為統計設計的 Seaborn。
Seaborn 是基於 Matplotlib 開發的高階繪圖函式庫,專門為統計視覺化設計。它內建多種適合統計分析的圖表類型,配色也更精緻,只要幾行程式碼就能畫出過去要寫十幾行才能完成的圖。今天會介紹四個常用的 Seaborn 圖表:直方圖、箱形圖、散佈圖矩陣與熱力圖,並學會用主題與調色盤統一圖表風格。
這篇會假設你已經裝好 Seaborn 0.13 以上版本,並熟悉基本的 Pandas 操作。如果你對 DataFrame 的操作還不熟,可以先回去複習 Day 17、Day 18。今天的重點在於「如何用 Seaborn 把資料的統計特徵快速視覺化」。
Seaborn 入門與主題設定
Seaborn 的使用方式和 Matplotlib 類似,但要記得先匯入並設定主題。常見的主題有 "darkgrid"、"whitegrid"、"dark"、"white"、"ticks",其中 "whitegrid" 是最常用的,因為它有淺色格線,閱讀數據時更不吃力。設定主題後,所有 Seaborn 圖表都會自動套用該風格。
import seaborn as sns
import matplotlib.pyplot as plt
sns.set_theme(style="whitegrid", palette="muted")
tips = sns.load_dataset("tips")
print(tips.head())
輸出:
total_bill tip sex smoker day time size
0 16.99 1.01 Female No Sun Dinner 2
1 10.34 1.66 Male No Sun Dinner 3
2 21.01 3.50 Male No Sun Dinner 3
3 23.68 3.31 Male No Sun Dinner 2
4 24.59 3.61 Female No Sun Dinner 4
sns.load_dataset("tips") 會從 Seaborn 內建的範例資料集中載入「小費」資料,記錄餐廳顧客的總消費、小費、性別、吸菸習慣、用餐時段等欄位。Seaborn 內建十多個範例資料集,很適合練習用。常用的還有 "iris"(鳶尾花)、"titanic"(鐵達尼號乘客)、"penguins"(企鵝形態資料)等,明天 Day 22 會實際用它們做探索分析。
直方圖與分佈圖:了解資料分佈
想知道一個數值欄位的分佈狀況(例如小費金額大多落在哪個區間),最常用的就是直方圖。Seaborn 的 histplot() 會自動分箱並畫出頻率長條;加上 kde=True 還會疊上一條平滑的密度曲線。直方圖回答的核心問題是「資料集中在哪裡、離散程度如何」。
fig, ax = plt.subplots(figsize=(7, 4))
sns.histplot(data=tips, x="tip", bins=20, kde=True, ax=ax)
ax.set_title("小費金額分佈")
ax.set_xlabel("小費(美元)")
ax.set_ylabel("次數")
plt.show()
輸出是一張直方圖,大部分小費集中在 2 到 4 美元之間,隨金額增加而快速遞減;右側那條曲線則是核心密度估計,能讓我們快速看出分佈的形狀與偏態。如果資料量更大或想同時比較多組分佈,可以改用 kdeplot()。bins 參數決定分箱數量,數字太小會看不出細節、太大又會讓圖變得破碎;實務上 20 到 50 之間通常是不錯的起點。
箱形圖:跨組別比較分佈
當我們想比較不同類別下某個數值欄位的分佈,例如「不同用餐時段的小費差異」,箱形圖(box plot)是最常用的圖。它會把中位數、四分位數、極端值一次畫出來,比長條圖多出很多資訊。箱形圖特別適合「類別不多、每組樣本數不少」的情境。
fig, ax = plt.subplots(figsize=(7, 4))
sns.boxplot(data=tips, x="day", y="total_bill", hue="time", ax=ax)
ax.set_title("各天各時段的總消費分佈")
ax.set_xlabel("星期")
ax.set_ylabel("總消費(美元)")
plt.show()
輸出是一張有四個箱子(週四到週日)的箱形圖,每個箱子再用 hue="time" 拆成午餐與晚餐兩組。每個箱子的中間橫線是中位數,箱子的上下邊是第 25 與第 75 百分位數,上下延伸出去的鬚鬚則是大部分資料的範圍,鬚外的點則是離群值。從這張圖就能看出週六晚餐的消費普遍較高。hue 參數可以把每個類別再拆成子組別,是 Seaborn 處理「兩個類別變數」最方便的工具。
散佈圖矩陣:一次看多個變數
當我們有多個數值欄位,想要快速觀察「哪些變數之間可能有相關」,pairplot() 是最快的選擇。它會把每一對變數畫成散佈圖,並在對角線上畫出每個變數的分佈圖。這種圖在 EDA 階段特別好用,可以一次掌握整份資料的結構。
sns.pairplot(tips, hue="sex", vars=["total_bill", "tip", "size"])
plt.show()
執行後會得到一張 3×3 的圖表網格:對角線上是三個變數各自的直方圖(依性別分色),非對角線則是兩兩變數之間的散佈圖。從圖上可以立刻看到 total_bill 與 tip 呈現明顯的正相關,但 size 與 tip 的相關就弱很多。pairplot() 是探索性資料分析(EDA)時的利器,但變數太多的時候圖會變得很大且擁擠,超過 5 個變數就要考慮只用相關矩陣搭配熱力圖。
熱力圖:呈現相關矩陣
散佈圖矩陣的缺點是當變數很多時,圖會變得太大不好閱讀。這時可以先用 DataFrame.corr() 算出相關係數矩陣,再交給 heatmap() 畫成熱力圖。熱力圖特別適合「變數數量多、想看整體相關結構」的場景,是模型特徵篩選的利器。
import numpy as np
numeric = tips[["total_bill", "tip", "size"]]
corr = numeric.corr()
fig, ax = plt.subplots(figsize=(6, 5))
sns.heatmap(corr, annot=True, fmt=".2f", cmap="coolwarm",
vmin=-1, vmax=1, ax=ax)
ax.set_title("數值欄位相關矩陣")
plt.show()
輸出是一張正方形的熱力圖,每個格子裡用顏色與數字標出相關係數(範圍 -1 到 1)。cmap="coolwarm" 把正相關畫成紅、負相關畫成藍,annot=True 把數字直接寫在格子上。這種圖一眼就能看出哪些變數彼此高度相關,特別適合做特徵篩選。在 Day 38 設計模型時,相關性過高的變數(多重共線性)通常會被移除或合併。
調色盤與自訂風格
Seaborn 的另一個強項是內建多套調色盤,讓圖表配色更協調。常見的調色盤有 "deep"、"muted"、"pastel"、"bright"、"dark"、"colorblind"。如果想指定特定數量的顏色,可以加數字,例如 "deep" 配 6 種顏色。配色不只是美觀問題,更影響資訊傳達——對色盲讀者友善的調色盤,能讓你的圖被更多人正確閱讀。
sns.set_theme(style="white", palette="Set2")
fig, ax = plt.subplots(figsize=(7, 4))
sns.boxplot(data=tips, x="day", y="tip", ax=ax)
ax.set_title("各天小費分佈(Set2 配色)")
plt.show()
換了配色與主題之後,圖會從原本的淺色格線變成白色背景、柔和色調,看起來更接近期刊或商業簡報的風格。Set2 是一組對色盲也友善的色票,適合在需要展示給多元觀眾時使用。如果報告中要列印成黑白,建議加上不同線型或標記形狀,讓讀者仍能區分各組。
結語
今天用 Seaborn 把 Day 20 的基礎延伸到了統計視覺化。直方圖讓我們看清分佈,箱形圖幫助我們跨組別比較,散佈圖矩陣與熱力圖則讓我們一眼掌握多變數之間的相關性。搭配主題與調色盤,幾行程式碼就能做出接近專業報告的圖表。Seaborn 還有很多更專門的圖,例如 violinplot()(小提琴圖)、jointplot()(聯合分佈圖)、clustermap()(階層分群的熱力圖),有興趣可以進一步閱讀官方文件。
明天,我們會把這兩天學到的 Pandas、Matplotlib、Seaborn 整合起來,做一次完整的資料探索實戰(EDA),把一份陌生的資料集從頭到尾看個仔細。
留言
張貼留言