owned this note
owned this note
Published
Linked with GitHub
# W5: 資料視覺化
## Source
- 應⽤機器學習於Python C1
- 大數據分析與資料探勘 W4
- colab 圖表顯示中文 : https://colab.research.google.com/github/willismax/matplotlib_show_chinese_in_colab/blob/master/matplotlib_show_chinese_in_colab.ipynb#scrollTo=AByB62T315mR
## 課堂投影片與練習
- [ ] **教學目標:**
* 理解資料視覺化在資料分析中的重要性.
* 熟悉使用 Matplotlib 繪製常見的統計圖表.
* 學習如何客製化圖表 (標題、座標軸、顏色、線條等).
* 了解如何在圖表中顯示中文.
* 掌握使用 Pandas 結合 Matplotlib 快速繪製圖表的方法.
* 能夠選擇適合的圖表類型來呈現不同類型的資料和關係.
* **適合對象:** 完成資料前處理與分析單元的同學,想要學習如何用圖形呈現分析結果.
---
- [ ] **為什麼需要資料視覺化?**
* 「一張圖勝過千言萬語」.
* **更好的理解資料:**
* 快速了解資料的分佈和趨勢.
* 更容易發現資料中的模式、異常值、或變數之間的關係.
* 彌補單純數字描述性統計的不足.
* **有效的溝通:** 將複雜的資料分析結果以直觀的方式呈現給他人.
* **協助決策:** 清晰的圖表有助於更明智的決策.
* 資料視覺化是資料探索 (Data Exploration) 的重要環節.
---
- [ ] **常用的資料視覺化工具**
* **Matplotlib:** Python 最主要的 2D 繪圖模組,功能強大且客製化選項多.
* 常用 `matplotlib.pyplot` 子模組,習慣縮寫為 `plt`.
* 與 Jupyter Notebook 相容性高 (`%matplotlib inline`).
* **Seaborn:** 基於 Matplotlib,提供了更美觀的預設風格和許多高階繪圖函數,特別適合統計圖形. (課程中可能提及但主要以 Matplotlib 和 Pandas 繪圖為主)
* **Pandas:** Pandas DataFrame 物件內建了繪圖功能,可以方便地直接從 DataFrame 繪製圖表,底層是使用 Matplotlib 實現.
---
- [ ] **Matplotlib 基本使用**
* **匯入 Matplotlib:** `import matplotlib.pyplot as plt`.
* **設定圖表風格:** `plt.style.use('風格名稱')`. 常用的風格有 'ggplot'.
* **繪製圖形:** 使用 `plt` 的各種函數 (如 `plt.plot()`, `plt.scatter()`, `plt.hist()`, `plt.bar()`, `plt.boxplot()`). 這些函數通常需要資料點的座標 (x, y 串列或 array).
* **顯示圖形:** `plt.show()`. 在 Jupyter Notebook 中使用 `%matplotlib inline` 後,通常可以省略 `plt.show()`,圖形會自動顯示.
```python=
import matplotlib.pyplot as plt
import numpy as np
# 設定風格
plt.style.use('ggplot')
# 生成範例資料
x = np.arange(0, 10, 1)
y = x ** 2
# 繪製折線圖
plt.plot(x, y, label='y = x^2')
# 加入標題與標籤
plt.title('example')
plt.xlabel('X axis')
plt.ylabel('Y axis')
plt.legend()
# 顯示圖形
plt.show()
```
---
- [ ] **常見圖表類型與繪製**
* **散佈圖 (Scatter Plot):** 呈現兩個變數之間的關係,常檢查相關性.
* `plt.scatter(x, y)`.
* **長條圖 (Bar Chart):** 呈現不同類別的數據大小比較,或類別變數的分佈狀態.
* `plt.bar(x_labels, y_values)`. x 軸通常是類別標籤,y 軸是數值.
* **直方圖 (Histogram):** 呈現單一數值變數的數據分佈頻率.
* `plt.hist(data_values, bins=數量)`. `bins` 指定分多少個區間.
* **折線圖 (Line Chart):** 呈現數據隨時間或其他有序變數變化的趨勢.
* `plt.plot(x_ordered, y_values)`. x 軸通常是時間或順序.
* **盒鬚圖 (Box Plot):** 呈現數據的分散情形、中位數、四分位數,並常用於識別異常值.
* `plt.boxplot(data_values_list)`.
* **熱圖 (Heatmap):** 使用顏色深淺表示矩陣中數值高低的圖,常用於顯示相關係數矩陣,快速了解變數之間的關聯性.
* 通常結合 Seaborn 繪製,但 Matplotlib 也可以實現.
```python=
import matplotlib.pyplot as plt
import numpy as np
# 散佈圖
np.random.seed(0)
x_scatter = np.random.rand(50) * 10
y_scatter = x_scatter + np.random.randn(50) * 5
plt.scatter(x_scatter, y_scatter)
plt.title('散佈圖')
plt.xlabel('X')
plt.ylabel('Y')
plt.show()
# 長條圖
categories = ['A', 'B', 'C', 'D']
values = [23, 45, 12, 30]
plt.bar(categories, values)
plt.title('長條圖')
plt.xlabel('類別')
plt.ylabel('數值')
plt.show()
# 直方圖
data_hist = np.random.randn(1000)
plt.hist(data_hist, bins=30)
plt.title('直方圖')
plt.xlabel('值')
plt.ylabel('頻率')
plt.show()
# 折線圖
x_line = np.arange(0, 10, 1)
y_line = np.sin(x_line)
plt.plot(x_line, y_line)
plt.title('折線圖')
plt.xlabel('X')
plt.ylabel('Y')
plt.show()
# 盒鬚圖
data_box = [np.random.randn(100) for _ in range(4)]
plt.boxplot(data_box)
plt.title('盒鬚圖')
plt.xlabel('組別')
plt.ylabel('值')
plt.show()
```
- 常見圖表類型與繪製 - Heatmap example
```python=
import matplotlib.pyplot as plt
import numpy as np
# 建立 10x10 的隨機資料矩陣
data = np.random.rand(10, 10)
# 繪製熱圖
plt.imshow(data, cmap='viridis', interpolation='nearest')
plt.colorbar() # 顯示色條
plt.title('Heatmap Example')
plt.xlabel('X Axis')
plt.ylabel('Y Axis')
plt.show()
```
---
- [ ] **課堂練習:繪製基本圖表**
1. **任務:** 載入波士頓房價資料集 (或使用前一個單元處理後的 DataFrame `df`)。
2. **任務:** 選擇兩個數值欄位 (例如 'RM' 代表平均房間數,'MEDV' 代表房價),繪製它們之間的**散佈圖**,觀察它們是否有相關性。
3. **任務:** 選擇一個數值欄位 (例如 'AGE' 代表房屋年齡),繪製其**直方圖**,觀察房屋年齡的分佈情況。
```python
import matplotlib.pyplot as plt
import pandas as pd
from sklearn.datasets import load_boston
import warnings
warnings.filterwarnings('ignore') # 忽略 sklearn 移除警告
# 載入資料(或接續使用上一堂課的Dataframe)
boston = load_boston()
df = pd.DataFrame(boston.data, columns=boston.feature_names)
# 任務 2:散佈圖
plt.scatter(df['RM'], df['MEDV'])
plt.title('房間數 vs 房價')
plt.xlabel('RM (平均房間數)')
plt.ylabel('Target (房價)')
plt.show()
# 任務 3:直方圖
plt.hist(df['AGE'], bins=20)
plt.title('房屋年齡分佈')
plt.xlabel('AGE (房屋年齡)')
plt.ylabel('頻率')
plt.show()
```
---
- [ ] **客製化圖表**
* **設定標題與座標軸名稱:**
* `plt.title('圖表標題')`
* `plt.xlabel('X 軸名稱')`
* `plt.ylabel('Y 軸名稱')`
* 可以設定 `fontsize` 調整字體大小.
* **設定座標軸範圍:**
* `plt.xlim(起始值, 終止值)`
* `plt.ylim(起始值, 終止值)`
* **設定座標軸刻度:**
* `plt.xticks(刻度位置列表, 刻度標籤列表)`
* `plt.yticks(...)`
* **顯示圖例 (Legend):**
* 在繪圖函數中設定 `label='數據系列名稱'`.
* 呼叫 `plt.legend()` 顯示圖例.
* **顯示格線 (Grid):** `plt.grid(True)`. 可以設定顏色、線型、寬度、透明度.
* **變換顏色與線條樣式:**
* 在繪圖函數中設定 `color='顏色'` (如 'r' 紅色, 'g' 綠色, 'b' 藍色, 或使用 RGB 色碼).
* 設定 `linestyle='線型'` (如 '--' 虛線, '-' 實線).
* 設定 `marker='標記樣式'` (如 'o' 圓點, 'x' 叉號).
---
- [ ] **在圖表中顯示中文**
* **問題:** Matplotlib 預設字體可能不包含中文字型,直接顯示中文可能會出現亂碼.
* **解決方法:**
1. **設定全局字體:** 修改 Matplotlib 的運行時配置 (`plt.rcParams`),將字體設定為支援中文的字體 (如 Windows 上的 'Microsoft JhengHei' 微軟正黑體 或 'SimHei' 黑體).
2. **指定特定文字的字體:** 使用 `matplotlib.font_manager.FontProperties` 指定特定標題或標籤的字體文件路徑.
```python
import matplotlib.pyplot as plt
import numpy as np
# 設定全局中文字體(請依照作業系統替換為可用的字體名稱)
# Windows:'Microsoft JhengHei'
# macOS:'Arial Unicode MS'
# Linux:'WenQuanYi Zen Hei'、'Noto Sans CJK TC' 等
plt.rcParams['font.family'] = 'Microsoft JhengHei'
plt.rcParams['axes.unicode_minus'] = False # 解決負號顯示問題
# 測試資料
x = np.linspace(-5, 5, 100)
y = x ** 2
# 中文圖表測試
plt.plot(x, y)
plt.title('測試中文標題')
plt.xlabel('X 軸 - 測試')
plt.ylabel('Y 軸 - 數值')
plt.show()
```
---
- [ ] **繪製多個圖表 (Multiple Plots)**
* **在同一張圖上繪製多條線或多個數據系列:** 直接多次呼叫繪圖函數即可. 不同函數呼叫會疊加在同一個座標軸上.
* **在一個圖表區 (Figure) 中排列多張圖表 (subplots):**
* 使用 `plt.subplot(橫列數, 直欄數, 圖表索引值)` 來指定接下來繪製的圖形要放在哪個位置. 圖表索引值從 1 開始計數.
* **在圖表區中使用相對位置排列圖表 (axes):**
* 使用 `plt.axes([與左邊界距離, 與下邊界距離, 長度, 寬度])`. 座標和長寬都是相對於圖表區的比例 (0 到 1 之間). 常用於繪製子母圖.
```python
import matplotlib.pyplot as plt
import numpy as np
# 方法一:同一圖表上繪製多條線
x = np.arange(1, 6)
y1 = x
y2 = x ** 2
plt.plot(x, y1, label='y = x')
plt.plot(x, y2, label='y = x²')
plt.title('兩條線比較')
plt.xlabel('X')
plt.ylabel('Y')
plt.legend()
plt.show()
# 方法二:使用 subplot 排列多張圖表
plt.figure(figsize=(10, 4))
# 左圖:折線圖
plt.subplot(1, 2, 1)
plt.plot(x, y2, color='blue')
plt.title('子圖 A')
# 右圖:長條圖
plt.subplot(1, 2, 2)
plt.bar(['A', 'B', 'C'], [5, 3, 7])
plt.title('子圖 B')
plt.tight_layout() # 自動調整間距
plt.show()
```
---
- [ ] **課堂練習:客製化與多圖繪製**
1. **任務:** 使用波士頓房價資料集 (df)。選擇 'RM' (平均房間數) 和 'MEDV' (房價) 繪製散佈圖。
2. **任務:** 為該散佈圖加上標題、X 軸名稱、Y 軸名稱。嘗試調整標題的字體大小。
3. **任務:** 設定圖表的 Y 軸範圍,讓它從 0 開始到 60。
4. **任務:** (進階) 在一個圖表區中,使用 `subplot` 將 'RM' vs 'MEDV' 的散佈圖和 'AGE' 的直方圖並列顯示 (例如 1 橫列 2 直欄)。
```python
import matplotlib.pyplot as plt
import pandas as pd
from sklearn.datasets import fetch_openml
# 載入波士頓房價資料集 (OpenML)
boston = fetch_openml(name="boston", version=1, as_frame=True)
df = boston.frame
# 任務 1, 2, 3:繪製散佈圖並加標題、設定軸範圍
plt.scatter(df['RM'], df['MEDV'])
plt.title('房間數 vs 房價 散佈圖', fontsize=14)
plt.xlabel('RM (平均房間數)')
plt.ylabel('MEDV (房價)')
plt.ylim(0, 60)
plt.show()
# 任務 4:subplot 畫兩張圖
plt.figure(figsize=(12, 5))
# 圖表 A:房間數 vs 房價(散佈圖)
plt.subplot(1, 2, 1)
plt.scatter(df['RM'], df['MEDV'])
plt.title('房間數 vs 房價')
plt.xlabel('RM')
plt.ylabel('MEDV')
# 圖表 B:AGE 分佈(直方圖)
plt.subplot(1, 2, 2)
plt.hist(df['AGE'], bins=20)
plt.title('房屋年齡分佈')
plt.xlabel('AGE')
plt.ylabel('頻率')
plt.tight_layout()
plt.show()
```
---
- [ ] **使用 Pandas 繪製圖表**
* **優點:** Pandas DataFrame 直接整合了繪圖功能,語法更簡潔方便.
* **如何使用:** 直接在 DataFrame 物件上呼叫 `.plot()` 方法.
* **指定圖表類型:** 使用 `kind` 參數,如 `kind='bar'`, `kind='line'`, `kind='scatter'`, `kind='hist'`, `kind='box'` 等.
* **設定圖表參數:** `.plot()` 方法也接受許多與 Matplotlib 相似的參數 (如 title, xlabel, ylabel, figsize, legend, grid, xlim, ylim 等).
* **在 Jupyter Notebook 中顯示圖形:** 需要先執行 `%matplotlib inline` 指令.
```python
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.datasets import fetch_openml
# 載入波士頓房價資料集
boston = fetch_openml(name='boston', version=1, as_frame=True)
df = boston.frame
# 繪製 'MEDV'(房價)的直方圖
df['MEDV'].plot(kind='hist', bins=20, title='房價分佈')
plt.xlabel('房價')
plt.ylabel('頻率')
plt.show()
# 繪製 'RM' vs 'MEDV' 的散佈圖
df.plot(kind='scatter', x='RM', y='MEDV', title='房間數 vs 房價')
plt.xlabel('平均房間數 (RM)')
plt.ylabel('房價 (MEDV)')
plt.show()
# 繪製多個欄位的盒鬚圖(檢查異常值)
df[['CRIM', 'ZN', 'INDUS']].plot(kind='box', title='CRIM, ZN, INDUS 的盒鬚圖')
plt.show()
```
---
- [ ] **課堂練習: 使用 Pandas 繪圖**
1. **任務:** 載入波士頓房價資料集 (或使用處理後的 DataFrame `df`)。
2. **任務:** 使用 Pandas 的 `.plot()` 方法,繪製 'CRIM' (人均犯罪率) 欄位的**直方圖**。為圖表加上標題。
3. **任務:** 使用 Pandas 的 `.plot()` 方法,選擇 'DIS' (距離市中心的加權平均距離) 和 'target' (房價) 繪製它們之間的**散佈圖**。為圖表加上標題和座標軸標籤。
4. **任務:** 使用 Pandas 的 `.plot()` 方法,繪製 'NOX' (一氧化氮濃度) 和 'PTRATIO' (學生-教師比例) 這兩個欄位的**盒鬚圖**,觀察它們的數據分佈和是否存在異常值。
```python
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.datasets import fetch_openml
# 載入資料
boston = fetch_openml(name='boston', version=1, as_frame=True)
df = boston.frame
# 任務 2:繪製 CRIM 的直方圖
df['CRIM'].plot(kind='hist', bins=30, title='犯罪率分佈')
plt.xlabel('CRIM (人均犯罪率)')
plt.ylabel('頻率')
plt.show()
# 任務 3:DIS vs MEDV 的散佈圖
df.plot(kind='scatter', x='DIS', y='MEDV', title='距離市中心距離 vs 房價')
plt.xlabel('DIS (距離市中心距離)')
plt.ylabel('MEDV (房價)')
plt.show()
# 任務 4:NOX 和 PTRATIO 的盒鬚圖
df[['NOX', 'PTRATIO']].plot(kind='box', title='NOX 與 PTRATIO 的盒鬚圖')
plt.ylabel('數值')
plt.show()
```
---
- [ ] **單元總結**
* 資料視覺化是理解資料、發現模式、和呈現分析結果的強大工具.
* Matplotlib 是 Python 中基礎且功能豐富的繪圖庫,提供多樣化的客製化選項.
* 掌握常見圖表類型 (散佈圖、長條圖、直方圖、折線圖、盒鬚圖、熱圖) 的適用情境和繪製方法.
* 學會如何設定圖表的標題、座標軸、圖例、格線等,以及處理中文顯示.
* 利用 Pandas DataFrame 的 `.plot()` 功能可以更快速、方便地進行常用圖表的繪製.
* 透過視覺化,我們可以更好地驗證資料前處理的效果,並為後續的模型建制提供洞察.