返回目錄
A
資料科學實戰:從數據到洞察 - 第 2 章
第2章 數據採集與清洗
發布於 2026-02-27 04:39
# 第2章 數據採集與清洗
資料科學的核心在於 **「資料」**。即使有最先進的演算法,如果輸入的資料品質欠佳,模型輸出的洞察也可能是誤導性的。此章節將帶領讀者從資料來源、採集技術,到清洗與品質保證的完整流程,為後續的 EDA、特徵工程與模型建置奠定堅實基礎。
---
## 2.1 資料來源分類
| 類型 | 特徵 | 典型例子 |
|------|------|----------|
| 結構化資料 | 固定 schema、表格化 | 資料庫表、CSV、Excel |
| 半結構化資料 | 標籤或層級化 | JSON、XML、Parquet |
| 非結構化資料 | 無明確 schema | 文字、影像、音訊、影片 |
| 流資料 | 持續、即時更新 | Kafka、Apache Flink、IoT sensor |
> **實務觀察**:金融交易記錄多為結構化資料;社群媒體貼文則屬於非結構化;即時風險監控常用流資料。
## 2.2 資料採集工具與技術
| 技術 | 主要用途 | 常用語言/框架 |
|------|----------|----------------|
| API | 結構化資料的遠端調用 | `requests`, `httpx`, `aiohttp` |
| Web Scraping | 抓取網頁資料 | `BeautifulSoup`, `Scrapy`, `Selenium` |
| ETL / ELT | 批次資料整合 | `Airflow`, `dbt`, `Luigi` |
| 流式平台 | 實時資料流 | `Kafka`, `Apache Pulsar`, `Azure Event Hubs` |
| 雲端儲存 | 大量原始資料 | AWS S3, GCP Cloud Storage, Azure Blob Storage |
> **小技巧**:對於需要高頻更新的金融行情,建議使用 WebSocket 取代 HTTP GET,能減少延遲與頻寬。
## 2.3 資料品質概念
1. **完整性 (Completeness)** – 資料是否遺漏關鍵欄位或紀錄。
2. **準確性 (Accuracy)** – 資料是否與真實情況相符。
3. **一致性 (Consistency)** – 多個資料來源在同一實體上是否相符。
4. **時效性 (Timeliness)** – 資料更新的延遲是否可接受。
5. **唯一性 (Uniqueness)** – 同一實體是否存在重複紀錄。
> **實務提醒**:在金融風控中,信用分數若缺失或不一致,模型可能高估或低估風險,導致損失。
## 2.4 常見資料清洗任務
| 任務 | 目的 | Python 範例 |
|------|------|------------|
| 缺失值處理 | 填補或移除不完整資料 | `df.dropna()`, `df.fillna(0)` |
| 異常值偵測 | 移除離群或錯誤輸入 | `np.where(df['col'] > threshold, np.nan, df['col'])` |
| 重複資料移除 | 避免多重計算 | `df.drop_duplicates()` |
| 格式統一 | 文字統一大小寫、日期格式 | `df['date'] = pd.to_datetime(df['date'])` |
| 資料型別轉換 | 確保型別一致 | `df['amount'] = df['amount'].astype(float)` |
### 範例:缺失值與異常值處理
```python
import pandas as pd
import numpy as np
# 讀取原始資料
raw = pd.read_csv('transaction_raw.csv')
# 缺失值填補
raw['amount'].fillna(raw['amount'].median(), inplace=True)
# 異常值檢測(假設 1% 的離群上限)
q1, q3 = raw['amount'].quantile([0.25, 0.75])
iqr = q3 - q1
lower, upper = q1 - 1.5*iqr, q3 + 1.5*iqr
raw.loc[(raw['amount'] < lower) | (raw['amount'] > upper), 'amount'] = np.nan
# 再次填補異常值
raw['amount'].fillna(raw['amount'].mean(), inplace=True)
raw.to_csv('transaction_clean.csv', index=False)
```
## 2.5 清洗工具與技巧
| 工具 | 特色 | 何時使用 |
|------|------|----------|
| Pandas | 適合單機中小規模資料 | < 10 億筆、記憶體 < 16GB |
| PySpark | 水平擴展、分散式處理 | > 10 億筆、需要分佈式計算 |
| SQL (PostgreSQL, BigQuery) | 直接在資料庫中清洗 | 資料已存於 RDBMS |
| OpenRefine | 直覺式資料探索 | 清洗表格、發現重複、標準化 |
| Data Wrangler | 交互式轉換 | 需求快速原型、視覺化轉換 |
### 使用 Spark 進行大規模資料清洗
```python
from pyspark.sql import SparkSession
from pyspark.sql.functions import col, mean, expr
spark = SparkSession.builder.appName('cleaning').getOrCreate()
raw = spark.read.csv('s3://bucket/transaction_raw.csv', header=True, inferSchema=True)
# 缺失值填補
clean = raw.na.fill({'amount': raw.selectExpr('percentile_approx(amount, 0.5)').first()[0]})
# 異常值篩選(以 3 倍 IQR 為界)
stats = clean.selectExpr('percentile_approx(amount, 0.25) as q1',
'percentile_approx(amount, 0.75) as q3').first()
q1, q3 = stats.q1, stats.q3
iqr = q3 - q1
lower, upper = q1 - 3*iqr, q3 + 3*iqr
clean = clean.where((col('amount') >= lower) & (col('amount') <= upper))
clean.write.mode('overwrite').csv('s3://bucket/transaction_clean.csv')
```
## 2.6 資料清洗流程設計
```
┌─────────────────────┐
│ 1️⃣ 需求分析 │
├─────────────────────┤
│ 2️⃣ 資料來源確認 │
├─────────────────────┤
│ 3️⃣ 取得資料(API / Scrape / ETL)│
├─────────────────────┤
│ 4️⃣ 初步檢查(EDA) │
├─────────────────────┤
│ 5️⃣ 清洗規則定義 │
├─────────────────────┤
│ 6️⃣ 資料轉換 (ETL/ELT) │
├─────────────────────┤
│ 7️⃣ 儲存與檢核 │
└─────────────────────┘
```
> **最佳實踐**:
> - **版本化**:每一次清洗都產生新的「clean」檔案,使用 Git 或 DVC 追蹤。
> - **自動化**:Airflow DAG 或 Prefect Flow 讓流程可重複執行,減少人為錯誤。
> - **日誌紀錄**:記錄每一步的行為(填補、移除、型別轉換),方便審計。
## 2.7 資料治理與合規
| 法規 | 主要要求 | 影響範疇 |
|------|----------|----------|
| GDPR (EU) | 隱私權保護、資料主體權益 | 敏感資料需匿名化或加密 |
| 個人資料保護法(台灣) | 個人資料蒐集、利用、保留 | 標籤化、加密、刪除 |
| PCI‑DSS | 信用卡資料安全 | 加密傳輸、最小權限存取 |
### 匿名化技巧
```python
# 進行哈希匿名化
raw['user_id'] = raw['user_id'].apply(lambda x: hash(x))
# 或使用 Faker 的 anonymizer
from faker import Faker
fake = Faker()
raw['ssn'] = raw['ssn'].apply(lambda _: fake.ssn())
```
> **關鍵提醒**:資料治理不只是清洗,更包含 *權限、版本、審計*。在金融機構,所有資料處理步驟必須可追蹤,避免合規風險。
## 2.8 案例實務:金融交易數據清洗
### 原始資料片段
```
date,user_id,amount,card_type,status
2023‑01‑01,123456,1000,visa,approved
2023‑01‑02,123456,,visa,declined
2023‑01‑02,123456,5000,visa,approved
2023‑01‑02,123456,5000,visa,approved # 重複
```
### 清洗流程
1. **缺失值**:`amount` 填補為中位數。
2. **異常值**:設定 `amount > 3000` 為離群,填補為 `NaN` 後再取均值。
3. **重複**:`drop_duplicates(subset=['date','user_id','card_type'])`。
4. **型別轉換**:將 `date` 轉為 `datetime`。
### 成效
| 變數 | 清洗前 | 清洗後 |
|------|--------|--------|
| 欄位數 | 5 | 5 |
| 缺失值數 | 1 | 0 |
| 重複紀錄 | 1 | 0 |
| 離群數 | 1 | 0 |
> **學習點**:此簡易流程已使資料符合「完整性」與「一致性」兩項品質指標,進一步提升 EDA 及模型效能。
## 2.9 小結
- **資料採集**:不同類型的資料需要不同的技術棧,選擇合適的工具能節省時間與成本。
- **資料清洗**:缺失值、異常值、重複資料等問題是常見的品質障礙,透過 Pandas、Spark 或 SQL 等工具可有效處理。
- **資料治理**:合規與治理是不可忽略的環節,尤其在金融、醫療等高風險領域。
- **實務案例**:金融交易數據的清洗流程示範了理論到實作的轉換,並說明了品質提升對模型效果的正向影響。
> **下一步**:第3章將以已清洗的資料為基礎,進行 **探索性資料分析 (EDA)**,發掘資料中的模式、分布與潛在關聯,進一步為特徵工程與模型選型提供洞察。