返回目錄
A
數據驅動決策:實務分析師的數據科學指南 - 第 3 章
第三章:資料清理與預處理
發布於 2026-03-02 19:11
# 第三章:資料清理與預處理
> 在任何數據科學專案中,資料清理(Data Cleaning)與預處理(Data Pre‑processing)是決定模型效能與決策可靠性的關鍵環節。這一章將系統說明缺失值處理、異常檢測以及特徵工程的基礎概念、方法與實務技巧,並提供可直接落地的程式碼範例。
---
## 1. 缺失值處理
### 1.1 為何缺失值重要
| 缺失類型 | 典型來源 | 可能影響 |
|----------|----------|----------|
| **整體缺失**(Missing Completely at Random, MCAR) | 隨機刪除、系統失效 | 估計偏差可忽略 |
| **條件缺失**(Missing at Random, MAR) | 問卷非回覆、傳感器失靈 | 需依其他變數補估 |
| **非隨機缺失**(Missing Not at Random, MNAR) | 敏感數據不報、商業機密 | 需要特別建模 |
> **小提示**:在實務中,先用資料探勘工具(如 Pandas Profiling、Sweetviz)快速可視化缺失結構,幫助決策。
### 1.2 補值策略
| 方式 | 適用情況 | Python 範例 |
|------|----------|-------------|
| **刪除**(Drop) | 變數缺失比例極低 (<5%) | `df.dropna(subset=['col'])` |
| **均值/中位數/眾數** | 連續數據、單一列缺失 | `df['col'].fillna(df['col'].median(), inplace=True)` |
| **前向/後向填充** | 時間序列、缺失連續段 | `df['col'].fillna(method='ffill')` |
| **插值**(Interpolation) | 時間序列、平滑需求 | `df['col'].interpolate(method='time')` |
| **KNN 補值** | 多維度關聯 | `from sklearn.impute import KNNImputer
imp = KNNImputer(n_neighbors=5)
df_imp = imp.fit_transform(df)` |
| **多重插補 (MICE)** | 複雜缺失模式 | `from sklearn.experimental import enable_iterative_imputer
from sklearn.impute import IterativeImputer
imp = IterativeImputer()
df_imp = imp.fit_transform(df)` |
> **實務提示**:若資料量大且缺失分佈複雜,建議先做 **特徵分群**,在各群內使用 KNN 或 MICE 進行補值,避免跨群不合理的補值。
### 1.3 補值流程建議
1. **資料檢測**:用 `df.isnull().sum()` 或 `df.isnull().mean()` 查看缺失比例。
2. **分類缺失類型**:根據業務背景判斷 MCAR/MAR/MNAR。
3. **選擇方法**:依缺失比例、資料類型、業務影響決定。
4. **實施補值**:寫成函式或使用 `Pipeline`,保持可重用。
5. **驗證**:補值後再次統計,確保缺失被處理且數值分佈未被扭曲。
---
## 2. 異常檢測
### 2.1 異常定義
> **異常(Outlier)**:在統計分布或機器學習模型中,與大多數樣本顯著不同的觀測值。異常既可能是測量錯誤,也可能是新現象(如詐騙、產品缺陷)。
### 2.2 檢測方法
| 方法 | 優點 | 局限 | 典型工具 |
|------|------|------|----------|
| **統計門檻**(IQR, Z‑score) | 簡單、直觀 | 受分佈影響、無法處理多變量 | `scipy.stats`, `numpy` |
| **聚類基礎**(DBSCAN) | 可發現任意形狀群 | 參數敏感、計算成本 | `scikit‑learn` |
| **Isolation Forest** | 針對高維資料設計 | 需要較多樣本 | `scikit‑learn` |
| **局部離群因子(LOF)** | 考慮鄰域密度 | 參數敏感、計算量大 | `scikit‑learn` |
| **貝葉斯方法**(Gaussian Mixture) | 可估計多峰分佈 | 需要假設分佈 | `scikit‑learn` |
### 2.3 範例:使用 Isolation Forest
python
import pandas as pd
from sklearn.ensemble import IsolationForest
# 假設 df 為數值型資料
model = IsolationForest(contamination=0.05, random_state=42)
# 建模
outlier_labels = model.fit_predict(df)
# -1 表示異常,1 表示正常
df['outlier'] = outlier_labels
# 篩選異常
outliers = df[df['outlier'] == -1]
print(f"偵測到 {len(outliers)} 個異常樣本")
### 2.4 實務操作
1. **視覺化先行**:利用箱型圖、散點圖確認異常模式。
2. **多層檢測**:先用統計門檻做粗篩,再用機器學習做細緻辨識。
3. **業務驗證**:將偵測結果交由領域專家審核,確認異常是否真實缺陷。
4. **處理決策**:異常可選擇刪除、修正、或保留並加權處理。
---
## 3. 特徵工程基礎
### 3.1 為何特徵工程重要
> 特徵是模型學習的語言,優質的特徵能顯著提升模型準確度、縮短收斂時間,並降低過擬合風險。
### 3.2 主要技術
| 技術 | 目的 | 範例 |
|------|------|------|
| **標準化 / 正規化**(StandardScaler, MinMaxScaler) | 消除量級差異 | `StandardScaler()` |
| **類別編碼**(One-Hot, Ordinal, Target Encoding) | 讓模型處理非數值類別 | `pd.get_dummies()` |
| **交互特徵**(PolynomialFeatures) | 捕捉變數之間非線性關係 | `PolynomialFeatures(degree=2)` |
| **降維**(PCA, t-SNE, UMAP) | 減少維度、去除噪聲 | `PCA(n_components=5)` |
| **時間特徵擷取**(Year, Month, Day, DayOfWeek, IsWeekend) | 捕捉季節性 | `df['month'] = df['date'].dt.month` |
| **文字向量化**(TF‑IDF, Word2Vec, Sentence‑BERT) | 將文本轉為數值 | `TfidfVectorizer()` |
| **缺失值特徵** | 讓模型利用缺失資訊 | `df['col_missing'] = df['col'].isnull().astype(int)` |
### 3.3 實戰範例:處理顧客資料集
python
import pandas as pd
from sklearn.preprocessing import StandardScaler, OneHotEncoder
from sklearn.compose import ColumnTransformer
from sklearn.pipeline import Pipeline
# 假設 df 內含 numeric, categorical, datetime 欄位
numeric_features = ['age', 'income', 'score']
categorical_features = ['gender', 'region']
datetime_features = ['signup_date']
# 1. 處理 datetime
def datetime_transformer(df):
df['signup_month'] = df['signup_date'].dt.month
df['signup_weekday'] = df['signup_date'].dt.weekday
return df.drop(columns=['signup_date'])
# 2. 建立 ColumnTransformer
preprocess = ColumnTransformer(
transformers=[
('num', StandardScaler(), numeric_features),
('cat', OneHotEncoder(handle_unknown='ignore'), categorical_features),
],
remainder='passthrough'
)
# 3. 組合 Pipeline
pipe = Pipeline(
steps=[
('datetime', FunctionTransformer(datetime_transformer)),
('preprocess', preprocess),
]
)
X_processed = pipe.fit_transform(df)
print(X_processed.shape)
> **提示**:在大型資料集中,建議將 Pipeline 轉存為 `pickle` 或 `joblib`,確保版本一致與重現性。
### 3.4 特徵選擇與評估
| 方法 | 說明 |
|------|------|
| **基於模型的重要性**(RandomForest, XGBoost) | 直接回傳 feature importance |
| **L1 正則化(Lasso)** | 把係數稀疏化,隱式選擇特徵 |
| **Recursive Feature Elimination (RFE)** | 迭代移除不重要特徵 |
| **資訊增益 / 卡方檢定** | 評估類別特徵與目標的相關度 |
> 透過交叉驗證與目標評估(如 AUC、RMSE)確認特徵選擇的實際效益。
---
## 4. 綜合工作流與最佳實踐
| 步驟 | 目標 | 工具 / 版型 |
|------|------|--------------|
| **資料探勘** | 確認數據質量、缺失、異常 | `pandas_profiling`, `sweetviz`, `dataprep` |
| **清理 & 補值** | 去除雜訊、填補缺失 | `pandas`, `scikit‑learn`, `PySpark` |
| **特徵工程** | 創造、轉換特徵 | `Pipeline`, `Featuretools`, `scikit‑feature` |
| **版本控制** | 保持 reproducibility | Git, DVC, MLflow Artifact Store |
| **測試** | 確保流程正確性 | `Great Expectations`, `pytest` |
| **自動化** | 週期性運行 | Airflow, Prefect, Dagster |
> **結語**:資料清理與預處理不僅是「把資料搞乾淨」的工作,更是一場持續的品質管理與探索性實驗。建議把清理流程視為「資料治理 pipeline」的一部分,持續監控資料品質,並以可重複、可測試的方式交付給後續建模團隊。
---
> **實務提醒**:在高頻更新的商業資料(如交易日誌、網站日志)中,盡量使用**增量清理**(只處理新到資料),並在資料管道中加入**資料品質監控**(例如每日自動報告缺失比例、異常數量),確保資料湖或資料倉庫的即時性與可靠性。