返回目錄
A
數據科學實務:從數據蒐集到模型部署的完整流程 - 第 4 章
第 4 章 探索性資料分析(EDA)與特徵工程
發布於 2026-02-22 18:46
# 第 4 章 探索性資料分析(EDA)與特徵工程
## 4.1 為什麼 EDA 重要
- **數據品質檢驗**:在進行建模之前,先確保資料沒有遺漏值、重複、格式錯誤等問題。若不先處理,模型往往會被噪音擾亂。
- **洞察發現**:EDA 讓你快速把握資料的分佈、相關性、潛在異常,這些洞察常能驅動特徵設計。
- **特徵工程方向**:透過統計檢驗和可視化,你可以判斷哪些變數值得進一步轉換、合併或刪除。
## 4.2 基礎工具與環境
| 主要工具 | 作用 |
|---|---|
| Pandas | 資料處理、缺失值填補、分組統計 |
| NumPy | 數值運算、向量化操作 |
| Matplotlib | 低階可視化、圖形調整 |
| Seaborn | 高階統計可視化、預設美化 |
| Scikit‑learn | 內建資料前處理工具、特徵選擇 |
安裝建議:
bash
pip install pandas numpy matplotlib seaborn scikit-learn
## 4.3 資料清理實務
### 4.3.1 讀取資料
python
import pandas as pd
df = pd.read_csv('data/titanic.csv')
print(df.head())
### 4.3.2 處理遺漏值
| 方法 | 適用情境 |
|---|---|
| `dropna()` | 數據量大,遺漏值比例極低 |
| `fillna()` | 需要保留行,常用均值/中位數/眾數 |
| `IterativeImputer` | 多變數缺失,需考慮互相影響 |
範例:用中位數填補 `Age` 欄位
python
median_age = df['Age'].median()
df['Age'].fillna(median_age, inplace=True)
### 4.3.3 去除重複
python
df.drop_duplicates(inplace=True)
### 4.3.4 轉換資料型別
python
df['Cabin'] = df['Cabin'].astype('category')
## 4.4 資料可視化與統計檢驗
### 4.4.1 分佈視覺化
python
import seaborn as sns
import matplotlib.pyplot as plt
plt.figure(figsize=(8,4))
sns.histplot(df['Age'], bins=30, kde=True)
plt.title('Age Distribution')
plt.xlabel('Age')
plt.ylabel('Count')
plt.show()
### 4.4.2 相關性矩陣
python
corr = df.corr()
plt.figure(figsize=(10,8))
sns.heatmap(corr, annot=True, cmap='coolwarm', fmt='.2f')
plt.title('Correlation Matrix')
plt.show()
### 4.4.3 盒鬍鬚圖檢測離群值
python
plt.figure(figsize=(6,4))
sns.boxplot(x=df['Fare'])
plt.title('Fare Boxplot')
plt.show()
### 4.4.4 統計檢驗範例
| 測試 | 目的 | 何時使用 |
|---|---|---|
| t‑test | 比較兩組均值差異是否顯著 | 兩個獨立樣本 |
| ANOVA | 多組均值差異 | >2 群組 |
| Chi‑square | 分類變數獨立性 | 交叉表 |
範例:獨立樣本 t‑test
python
from scipy import stats
male = df[df['Sex']=='male']['Fare']
female = df[df['Sex']=='female']['Fare']
t_stat, p_val = stats.ttest_ind(male, female)
print(f't‑stat={t_stat:.3f}, p={p_val:.3f}')
## 4.5 特徵工程概念
### 4.5.1 特徵選擇
| 方法 | 優點 | 缺點 |
|---|---|---|
| Filter(相關係數) | 簡單快速 | 只考慮單變數 |
| Wrapper(Recursive Feature Elimination, RFE) | 考慮模型交互 | 計算成本高 |
| Embedded(L1 正則化、Tree‑based importance) | 同時進行模型訓練 | 依賴模型類型 |
範例:使用 `SelectKBest` + `f_regression`
python
from sklearn.feature_selection import SelectKBest, f_regression
X = df.drop(columns=['Survived'])
y = df['Survived']
selector = SelectKBest(score_func=f_regression, k=5)
X_new = selector.fit_transform(X, y)
print('Selected feature mask:', selector.get_support())
### 4.5.2 編碼技巧
| 類型 | 方法 |
|---|---|
| Binary (True/False) | `df['Sex'].map({'male':0,'female':1})` |
| Label | `LabelEncoder()` | 只適合有順序的類別 |
| One‑Hot | `pd.get_dummies()` | 可能造成維度爆炸 |
| Target / Mean Encoding | 把類別轉成目標均值 | 需要避免資訊洩漏 |
| Frequency Encoding | 轉成類別出現頻率 | 只適合高 cardinality |
範例:One‑Hot + Frequency
python
# One‑Hot
sex_ohe = pd.get_dummies(df['Sex'], prefix='Sex', drop_first=True)
# Frequency Encoding
freq = df.groupby('Embarked')['Survived'].mean()
df['Embarked_freq'] = df['Embarked'].map(freq)
### 4.5.3 特徵縮放
| 方法 | 適用範例 |
|---|---|
| StandardScaler | 需要正態分佈假設 | 樹模型不必須 |
| MinMaxScaler | 範圍壓縮到 0‑1 | 異常值影響大 |
| RobustScaler | 對離群值不敏感 | 中位數基準 |
範例:使用 `RobustScaler`
python
from sklearn.preprocessing import RobustScaler
scaler = RobustScaler()
df['Age_scaled'] = scaler.fit_transform(df[['Age']])
## 4.6 高階特徵
### 4.6.1 交互特徵
python
# 舉例:Age 與 Fare 交互
X['Age_Fare'] = df['Age'] * df['Fare']
### 4.6.2 時間序列特徵(若有時間戳)
| 生成特徵 | 例子 |
|---|---|
| 年月日 | `datetime.dt.year` |
| 時間 | `datetime.dt.hour` |
| 工作日/週末 | `datetime.dt.weekday` |
### 4.6.3 多元尺度轉換
| 轉換 | 目的 |
|---|---|
| Log | 把右偏分佈變成近似正態 | `Fare`, `TotalCharges` |
| Box‑Cox | 提升正態性,同時可處理 0 或負值 | `salary` |
| PowerTransformer(Yeo‑Johnson) | 處理非正態分佈 |
範例:Log 轉換
python
import numpy as np
df['Fare_log'] = np.log1p(df['Fare'])
## 4.7 維度縮減
- **PCA**:保持方差比例,適用於連續特徵。
- **t‑SNE / UMAP**:可視化高維資料,發現群聚結構。
範例:PCA
python
from sklearn.decomposition import PCA
pca = PCA(n_components=2)
principal = pca.fit_transform(df.select_dtypes(include='number'))
print('Explained variance ratio:', pca.explained_variance_ratio_)
## 4.8 EDA 與特徵工程最佳實踐
1. **資料版本控制**:使用 `DVC` 或 Git‑LFS 追蹤原始資料。
2. **自動化 EDA**:寫腳本或 notebook 產生報表,使用 `pandas‑profiling` 或 `sweetviz`。
3. **記錄決策**:在 Jupyter notebook 或 Google Sheet 中記錄為什麼採用某種缺失值填補或編碼方式。
4. **避免資料洩漏**:在填補缺失值或編碼前,先在訓練集與測試集分開處理,或使用 `Pipeline`。
5. **特徵重要性評估**:結合模型(如 RandomForest)或 SHAP 進行解釋,幫助挑選關鍵特徵。
## 4.9 小結
- EDA 讓資料品質、分佈、相關性等層面可視化,成為特徵工程的基礎。
- 清理流程應包括缺失值處理、重複移除、型別轉換與資料型態統一。
- 可視化工具(hist、heatmap、boxplot、scatter)與統計檢驗(t‑test、ANOVA、Chi‑square)能快速發現結構性問題。
- 特徵工程涵蓋特徵選擇、編碼、縮放、交互與降維,這些技巧將直接影響模型效能與可解釋性。
- 建議將 EDA 步驟寫成腳本或 Jupyter notebook,並加入單元測試與 CI/CD 以保持重現性。
> **實作練習**:以 Titanic 數據為例,完成上述所有 EDA 步驟並將特徵輸出為 `train_X.csv` 與 `train_y.csv`,供後續建模使用。