Learning Objectives
- 說出 Figure 與 Axes 的關係,用 `fig, ax = plt.subplots()` 畫圖並加上標題與軸標籤
- 用 `plt.subplots(1, 2)` 在同一張圖裡放好幾個座標區
- 畫出折線圖、長條圖、散布圖、直方圖與箱形圖
- 依問題的種類(比較、分布、關係、組成、隨時間變化)選擇合適的圖表
同一份資料,畫錯圖就看不出答案
分析做到最後,大多要用一張圖把結果交給別人看。圖畫得好,讀者幾秒鐘就看懂;圖選錯了,資料再正確,讀者也看不出你要說的事。
選圖之前先問:這張圖要回答什麼問題? 常見的問題可以分成五類:
| 問題 | 例子 | 常用的圖 |
|---|---|---|
| 比較 | 各系的平均讀書時數誰高 | 長條圖 |
| 分布 | 通勤時間大多落在哪裡、多分散 | 直方圖、箱形圖 |
| 關係 | 期中高的人期末也高嗎 | 散布圖 |
| 組成 | 各系占全體的比例 | 長條圖、圓餅圖(塊數少時) |
| 隨時間變化 | 每週氣溫怎麼變 | 折線圖 |
這一課用 matplotlib 畫出這五種圖。資料是 weather.csv、students.csv、grades.csv,都是程式產生的模擬資料,不是任何學校或氣象站的真實資料。
Figure 與 Axes:一張紙和紙上的座標區
matplotlib 的一張圖有兩層:
- Figure(圖):整張紙,決定大小(
figsize=(寬, 高),單位是英寸)。 - Axes(座標區):紙上的一個座標系統,有自己的 x 軸、y 軸、標題。一張 Figure 可以放好幾個 Axes。
建議的寫法是先用 plt.subplots() 同時拿到兩者,再呼叫 Axes 的方法畫圖:
fig, ax = plt.subplots(figsize=(8, 3.4)) # 一張圖、一個座標區
ax.plot(x, y) # 折線
ax.set_xlabel("日期") # x 軸標題
ax.set_title("每日氣溫") # 這個座標區的標題
plt.show()
| Axes 的方法 | 畫什麼 |
|---|---|
ax.plot(x, y) |
折線圖 |
ax.bar(類別, 數值)、ax.barh(...) |
長條圖(直的、橫的) |
ax.scatter(x, y) |
散布圖 |
ax.hist(數值, bins=12) |
直方圖 |
ax.boxplot([第一組, 第二組]) |
箱形圖 |
ax.pie(數值, labels=...) |
圓餅圖 |
第 9 課用過的 plt.title()、series.plot.barh() 也能畫圖,它們會畫在「目前的」座標區上;只有一張圖時很方便,圖一多就容易畫錯地方,所以這一課一律用 ax. 開頭的寫法。
逐步看:Figure、Axes 與折線圖
注意第 6 行:plt.subplots 一次給你兩個物件。之後每一行都是在 ax 這個座標區上加東西,最後 plt.show() 才把圖畫出來。
逐步看:一張圖放兩個座標區,長條圖與散布圖
plt.subplots(1, 2) 會建立 1 列 2 欄、共兩個座標區。左邊回答「比較」,右邊回答「關係」。
看分布:直方圖與箱形圖
直方圖把數值分成幾個等寬的區間(bins),數每個區間有幾筆,用長條的高度表示。它回答「大多數落在哪裡、有沒有長尾巴、有沒有兩個高峰」。
區間分得太少會看不出形狀,太多會變得鋸齒狀,通常從 10~20 個試起。
箱形圖(box plot)用五個數字摘要一組資料:箱子的下緣、中線、上緣是第 1 四分位數、中位數、第 3 四分位數,兩端的線(鬚)延伸到不算極端的最小與最大值,鬚外面的點是可能的極端值(第 15 課會算)。 箱形圖很省空間,好幾組並排比較分布時特別好用。
逐步看:直方圖與並排的箱形圖
左邊看一個變數的分布,右邊把四門課的期末成績並排比較。
選圖的幾個原則
- 先寫下問題,再選圖。 同一份資料可以回答不同的問題,要用的圖也不同。
- 長條圖的 y 軸從 0 開始。 長條用「長度」表示數量,截掉一段就會誇大差異(下一課專門談)。折線圖看的是變化,y 軸不一定要從 0 開始。
- 折線表示有順序、相鄰點之間連續。 時間資料適合;系所、課程這種沒有順序的類別不要連線。
- 類別多時,依數值排序、改用橫的長條(
barh),標籤比較放得下。 - 圓餅圖只用在塊數少、加起來是一個整體的時候。 要精確比較大小,用長條圖。
- 每張圖都要有標題、軸標題(含單位),用到模擬或推估的資料要註明。
實作:各年級的每週讀書時數
讀入 students.csv,依年級(year)分組,算出每週讀書時數(study_hours)的平均,四捨五入到小數 1 位後印出。
接著用 fig, ax = plt.subplots() 把結果畫成長條圖,加上 x 軸、y 軸標題和圖的標題,最後 plt.show()。
(系統只比對印出的文字;圖會出現在輸出區,自己檢查看看。)
小測驗:圖與座標區
下面程式會印出什麼?
import matplotlib.pyplot as plt
fig, axes = plt.subplots(2, 3)
print(axes.shape)
fig, ax = plt.subplots() 之後,要幫這個座標區加上 y 軸標題,應該寫哪一行?
下面程式會印出什麼?(np.histogram 回傳每個區間的筆數,和直方圖的長條高度相同)
import numpy as np
counts, edges = np.histogram([1, 2, 2, 3, 9], bins=2, range=(0, 10))
print(counts)
小測驗:選對圖表
你想知道 200 位學生的每週睡眠時數大多落在哪裡、分布是否對稱,最適合哪一種圖?
為什麼「各系平均成績」不適合畫成折線圖?
想比較六門課的期末成績分布(中位數、分散程度、有沒有極端值),最適合哪一種圖?
重點整理
- Figure 是整張圖,Axes 是圖上的座標區;
fig, ax = plt.subplots()一次拿到兩者,plt.subplots(1, 2)拿到兩個座標區。 - 在
ax上畫:plot(折線)、bar/barh(長條)、scatter(散布)、hist(直方圖)、boxplot(箱形圖)、pie(圓餅);再用set_title、set_xlabel、set_ylabel加標題。 - 先問問題再選圖:比較用長條、分布用直方圖或箱形圖、關係用散布圖、組成用長條或圓餅(塊數少時)、隨時間變化用折線。
- 長條圖的 y 軸從 0 開始;沒有順序的類別不要連線;標題、軸標題與單位一個都不能少。
- 下一課看「畫得出來,但會誤導」的圖:截斷的軸、雙軸、面積錯覺,以及怎麼用標題、註記和小倍數把圖說清楚。