Python 資料清理與轉換
簡介
在資料科學與機器學習的工作流程中,資料清理與轉換(Data Cleaning & Transformation)是不可或缺的基礎步驟。即使模型再先進,若輸入的資料品質不佳,最終的預測結果也會受到嚴重影響。
本單元旨在說明如何使用 Python 內建與常見的第三方套件(如 pandas、numpy、re)快速、可靠地完成資料清理與格式轉換,幫助讀者在實務專案中建立乾淨、結構化的資料集。
核心概念
1. 為什麼需要資料清理?
- 缺失值(NaN、空字串)會導致計算錯誤或模型無法收斂。
- 重複資料 會讓統計結果偏斜。
- 不一致的格式(日期、金額、編碼)會讓後續的合併或分組操作變得困難。
2. 常用套件與資料結構
| 套件 | 主要功能 | 常見資料結構 |
|---|---|---|
pandas |
高效能資料框(DataFrame)操作 | DataFrame、Series |
numpy |
向量化運算、缺失值處理 | ndarray |
re |
正規表達式文字處理 | 文字字串 |
小技巧:在 Jupyter Notebook 中,使用
%matplotlib inline可以即時檢視清理前後的分布圖,幫助判斷是否已成功處理異常值。
3. 缺失值處理
import pandas as pd
import numpy as np
# 建立示範 DataFrame
df = pd.DataFrame({
"姓名": ["Alice", "Bob", np.nan, "David", "Eve"],
"年齡": [25, np.nan, 30, 22, None],
"收入": ["$3,200", "$4,500", "$5,000", None, "$2,800"]
})
# 1. 檢視缺失值概況
print(df.isna().sum())
# 2. 用特定值填補(例如年齡以平均值填補)
df["年齡"] = df["年齡"].fillna(df["年齡"].mean())
# 3. 刪除全為缺失的列
df = df.dropna(subset=["姓名"])
print(df)
以上範例展示了 檢視、填補與刪除 三種常見缺失值處理方式。對於數值欄位,使用平均值或中位數填補是最簡單的做法;對於文字欄位,則可考慮填入
"未知"或直接刪除該列。
4. 重複資料與不一致格式
# 假設有重複的交易紀錄
transactions = pd.DataFrame({
"交易編號": [101, 102, 101, 103, 104, 102],
"金額": [1000, 1500, 1000, 2000, 2500, 1500]
})
# 1. 找出重複列
dup = transactions.duplicated(subset=["交易編號"], keep=False)
print("重複列:\n", transactions[dup])
# 2. 移除重複(保留第一筆)
transactions_clean = transactions.drop_duplicates(subset=["交易編號"], keep="first")
print("移除重複後:\n", transactions_clean)
注意:
duplicated()預設只檢查全列相同,若只想比較特定欄位,請使用subset參數。
5. 日期與時間的標準化
# 原始資料中日期格式混雜
raw_dates = pd.Series(["2023/01/15", "15-02-2023", "2023.03.20", "April 5, 2023"])
# 使用 pandas.to_datetime 進行彈性解析
clean_dates = pd.to_datetime(raw_dates, errors="coerce", infer_datetime_format=True)
print(clean_dates)
errors="coerce"會把無法解析的值轉成NaT(類似 NaN),方便後續的缺失值處理。
6. 文字資料的清理(正規表達式)
import re
# 假設有一欄金額資料,包含美元符號、逗號與空白
money_series = pd.Series([" $3,200 ", "$4,500", "5000", "USD 2,800"])
def clean_money(val):
# 移除非數字與小數點的字元
num = re.sub(r"[^\d.]", "", str(val))
return float(num) if num else np.nan
cleaned_money = money_series.apply(clean_money)
print(cleaned_money)
透過
re.sub()可以快速去除不需要的符號,將文字型別的金額轉成 浮點數,為後續的數值分析做好準備。
7. 資料類型轉換(Casting)
# 先前的 DataFrame
df["收入"] = cleaned_money # 直接指派轉換後的 Series
# 確認欄位類型
print(df.dtypes)
# 如需將類別變數轉成 one‑hot 編碼
df_onehot = pd.get_dummies(df["姓名"], prefix="姓名")
print(df_onehot.head())
為了避免 類型不匹配 的錯誤,建議在完成清理後,使用
astype()明確指定欄位的資料型別。
常見陷阱與最佳實踐
| 陷阱 | 說明 | 最佳實踐 |
|---|---|---|
| 直接修改原始 DataFrame | 會導致難以追蹤的副作用 | 使用 df.copy() 產生副本,或在 Notebook 中保留原始變數 |
| 忽略時間區間 | 日期時間若未統一時區,會在合併或計算差異時出錯 | 轉換為 UTC 或同一時區 (tz_convert) |
| 過度填補缺失值 | 用平均值填補過多會降低資料變異性 | 先分析缺失機制(MCAR、MAR、MNAR),必要時考慮刪除或使用模型預測填補 |
| 正規表達式寫得太寬鬆 | 可能把不相關的字元也去除 | 測試正則表達式於樣本資料,必要時加上斷言或限定字元範圍 |
| 忘記重新設定索引 | 刪除列或合併後索引可能不連續,導致後續迭代錯誤 | 使用 reset_index(drop=True) 重新整理索引 |
小提醒:在大型資料集上執行
apply()會較慢,盡量改用向量化的pandas或numpy方法(如str.replace、astype)。
實際應用場景
金融交易資料
- 需要先將交易時間標準化、去除重複交易、將金額文字轉為數值,再計算每日、每月的交易量與風險指標。
電商產品評論
- 清理評論文字中的 HTML 標籤、表情符號,並將評分欄位轉為整數,以便進行情感分析或建立推薦系統。
醫療病歷資料
- 針對缺失的血壓、血糖值使用插值或模型預測填補,統一日期格式(出生日期、檢驗日期),確保個資去識別化後再進行統計分析。
社群媒體抓取
- 從 API 抓取的 JSON 常包含巢狀結構,需使用
json_normalize展平,並將時間戳記轉成可讀的 datetime,最後去除重複貼文或廣告。
- 從 API 抓取的 JSON 常包含巢狀結構,需使用
總結
資料清理與轉換是 資料科學流程的第一道關卡,好與壞直接決定後續分析與模型的可靠性。本文重點回顧如下:
- 缺失值、重複值與不一致格式 是最常見的問題,使用
pandas的isna、fillna、drop_duplicates等函式即可快速處理。 - 日期、時間與文字 需要透過
to_datetime、正規表達式等方式統一格式,避免在合併或計算時產生錯誤。 - 資料類型的明確轉換(Casting)與 one‑hot 編碼 能讓模型直接接受乾淨的特徵。
- 避免常見陷阱,如直接修改原始資料、過度填補或忽略時區,並遵循最佳實踐(使用副本、向量化運算)。
掌握上述技巧後,你就能在 金融、電商、醫療、社群等多種領域,快速把雜亂的原始資料轉化為可供分析與建模的高品質資料集。祝你在 Python 資料處理的旅程中,越走越順!