返回目錄
A
數據科學實戰:從問題到洞見 - 第 5 章
第5章 探索性資料分析(EDA)
發布於 2026-03-05 11:22
# 第5章 探索性資料分析(EDA)
> **探索性資料分析(EDA)** 是在任何機器學習項目中不可或缺的階段。它幫助你快速了解資料特性、發現潛在問題、確定特徵關係,並為後續的特徵工程與模型選擇奠定基礎。以下內容將從統計摘要、分布視覺化、相關性矩陣、群聚洞察四個面向,逐步引導你完成完整且可重複的 EDA 流程。
---
## 5.1 統計摘要
統計摘要提供了對數值特徵的一般性描述,通常包含**均值、標準差、最小值、最大值、四分位數**等指標。對於類別特徵,則以**頻次表**呈現。
| 量化特徵 | 值 | 描述 | 例子 |
|---------|-----|------|------|
| Min | 0 | 最小值 | 年齡 0 歲 |
| 25th Percentile | 18 | 第一四分位 | 年齡 18 歲 |
| Median | 35 | 中位數 | 35 歲 |
| 75th Percentile | 50 | 第三四分位 | 50 歲 |
| Max | 80 | 最大值 | 80 歲 |
| Mean | 34.2 | 平均值 | 34.2 歲 |
| Std | 9.8 | 標準差 | 9.8 歲 |
### 實作範例
python
import pandas as pd
import matplotlib.pyplot as plt
# 讀取資料
url = 'https://raw.githubusercontent.com/mwaskom/seaborn-data/master/titanic.csv'
df = pd.read_csv(url)
# 選擇數值列
numeric_cols = df.select_dtypes(include=['number']).columns
# 計算摘要統計
summary = df[numeric_cols].describe().T
print(summary[['count', 'mean', 'std', 'min', '25%', '50%', '75%', 'max']])
> **實戰提示**:將 `summary` 輸出成 JSON 並註冊到 MLflow Parameters,方便模型訓練時自動拉取統計基線。
## 5.2 分布視覺化
視覺化是 EDA 的核心工具,能快速揭示分布偏斜、離群值、雙峰等特徵。
### 1. 直方圖與 KDE
python
import seaborn as sns
plt.figure(figsize=(10, 4))
sns.histplot(df['age'], bins=20, kde=True, color='steelblue')
plt.title('Age Distribution')
plt.xlabel('Age')
plt.ylabel('Count')
plt.tight_layout()
plt.show()
### 2. 箱型圖(Box Plot)
python
plt.figure(figsize=(8, 5))
sns.boxplot(x='sex', y='age', data=df, palette='Set2')
plt.title('Age by Sex')
plt.tight_layout()
plt.show()
### 3. 熱度圖(Heatmap)顯示缺失值
python
plt.figure(figsize=(12, 6))
sns.heatmap(df.isnull(), cbar=False, yticklabels=False, cmap='viridis')
plt.title('Missing Value Heatmap')
plt.show()
> **最佳實務**:
> - **單一變數視覺化**:先查看直方圖 + KDE,然後確認箱型圖。若發現離群值,考慮是否需要處理。
> - **缺失值可視化**:使用熱度圖或 `missingno` 直觀展示缺失分佈,幫助決策缺失處理方式。
> - **可重複性**:將視覺化腳本打包成函式,並在 CI Pipeline 中執行。若圖形與前一次結果差異超過閾值,自動通知開發者。
## 5.3 相關性矩陣
相關性矩陣揭示特徵之間的線性關係。常用的係數有**皮爾森(Pearson)**、**斯皮爾曼(Spearman)**、**肯德爾(Kendall)**。
python
corr_matrix = df[numeric_cols].corr(method='pearson')
plt.figure(figsize=(10, 8))
sns.heatmap(corr_matrix, annot=True, fmt='.2f', cmap='coolwarm', vmin=-1, vmax=1)
plt.title('Pearson Correlation Matrix')
plt.tight_layout()
plt.show()
### 重要觀察點
| 觀察 | 意義 | 需注意事項 |
|------|------|------------|
| 高相關 | 可能存在多重共線性 | 影響模型解釋性,可能需要刪除或合併特徵 |
| 負相關 | 反向關係 | 不一定是錯誤,但需確認業務邏輯 |
| 低相關 | 可被視為獨立特徵 | 仍可能在非線性模型中貢獻大 |
> **實戰提示**:若使用 **非線性模型**(如 XGBoost、CatBoost),相關性矩陣的價值較低,但仍可用於初步過濾無關特徵。
## 5.4 群聚洞察(Cluster Analysis)
在沒有明確目標變數時,**聚類**可以揭示資料內在結構,協助資料切分或發現異常。
### 1. K‑Means 聚類示例
python
from sklearn.preprocessing import StandardScaler
from sklearn.cluster import KMeans
# 選取關鍵特徵
features = df[['age', 'fare']].dropna()
# 標準化
scaler = StandardScaler()
scaled = scaler.fit_transform(features)
# 估算最佳 K 值(Elbow Method)
inertia = []
for k in range(1, 11):
kmeans = KMeans(n_clusters=k, random_state=42)
kmeans.fit(scaled)
inertia.append(kmeans.inertia_)
plt.figure(figsize=(8,4))
plt.plot(range(1, 11), inertia, marker='o')
plt.xlabel('Number of clusters (k)')
plt.ylabel('Inertia')
plt.title('Elbow Method for K‑Means')
plt.show()
### 2. 以最佳 k 進行聚類並可視化
python
k_opt = 4
kmeans = KMeans(n_clusters=k_opt, random_state=42)
cluster_labels = kmeans.fit_predict(scaled)
plt.figure(figsize=(8,5))
sns.scatterplot(x=features['age'], y=features['fare'], hue=cluster_labels, palette='tab10')
plt.title(f'K‑Means Clusters (k={k_opt})')
plt.xlabel('Age')
plt.ylabel('Fare')
plt.legend(title='Cluster')
plt.show()
### 3. 發現異常(Outlier)
python
# 距離平方(Sum of Squared Distances)
dist_sq = kmeans.transform(scaled) ** 2
# 取最近聚類距離的最大值
threshold = dist_sq.max(axis=1).mean() + 3 * dist_sq.max(axis=1).std()
outliers = np.where(dist_sq.max(axis=1) > threshold)[0]
print('Potential outliers indices:', outliers)
> **洞見**:聚類可以協助:
> - **資料切分**:針對不同群聚採取不同特徵工程或模型。
> - **異常偵測**:遠離中心點的樣本可能為資料錯誤或業務異常。
> - **特徵選擇**:聚類結果可作為新的「群聚標籤」特徵輸入模型。
## 5.5 實務建議與重複執行
| 步驟 | 工具 | 重點 | 典型陷阱 |
|------|------|------|----------|
| 1. 資料載入 | Pandas / Spark | 確認檔案編碼、缺失值 | 未處理的 NaN 會導致 `describe()` 異常 |
| 2. 統計摘要 | Pandas | 計算全量摘要 | 不同資料型態(int vs float)造成誤差 |
| 3. 視覺化 | Matplotlib / Seaborn / Plotly | 交互式儀表板 | 視覺化太複雜,難以快速洞察 |
| 4. 相關性 | Scikit‑learn / Pandas | 觀察高相關 | 多重共線性忽略,影響模型解釋 |
| 5. 聚類 | Scikit‑learn / HDBSCAN | 觀察群聚結構 | 未標準化會導致聚類偏差 |
| 6. 迭代 | CI/CD / Jupyter Notebook | 確保可重複 | 版本不一致,導致結果不一致 |
### 重複性與追蹤
1. **腳本化**:將 EDA 代碼寫成 Python 模組,使用 `pytest` 或 `unittest` 進行單元測試。
2. **版本管理**:使用 Git 提交腳本與資料描述文件,保持歷史紀錄。
3. **結果儲存**:將圖表、摘要統計與相關矩陣輸出為 JSON / CSV,並註冊至 MLflow,確保每次實驗都有可追溯的基線。
4. **CI Pipeline**:在 GitHub Actions / GitLab CI 中執行 EDA 腳本,若結果偏差超過 5% 自動觸發通知。
## 5.6 小結
- **EDA 是資料治理的前置工作**:品質、完整性、可追溯性都需要在此確認。
- **工具選擇**:Python 與 Spark 在語法上相似,但效能與擴充性不同,需依據資料規模與團隊熟悉度選擇。
- **特徵洞見**:不是一成不變;隨著資料流更新與業務變化,需要定期重新進行 EDA。
- **可視化**:既是理解工具,也是溝通橋樑;保持圖表可重複產生、易於解讀。
- **CI 中的可視化**:建議將可視化納入 CI pipeline,若圖表偏差自動提醒開發者。
> **挑戰**:在分散式環境下,繪圖往往被忽略,結果導致「看不見」的數據異常。建議將可視化納入 CI pipeline,若圖表偏差自動提醒開發者。
---
**接下來**:我們將進入 **機器學習與模型建構** 的階段,將這些洞見轉化為可操作的預測邏輯。