本文 AI 產出,尚未審核
pandas DataFrame 操作實務指南
簡介
在 Python 的資料科學生態系中,pandas 是最常被使用的資料處理套件。它提供了功能強大的 DataFrame 結構,讓我們能以類似資料庫表格的方式,彈性且高效地進行清理、轉換與分析。無論是日常的 CSV 匯入、金融時間序列的切割,或是機器學習前的特徵工程,DataFrame 都是不可或缺的基礎工具。
本篇文章針對 初學者到中級開發者,從核心概念到實務技巧,系統性說明如何操作 pandas DataFrame,並提供多個可直接套用的程式碼範例,協助你在真實專案中快速上手、避免常見陷阱。
核心概念
1️⃣ 建立與檢視 DataFrame
| 方法 | 說明 |
|---|---|
pd.DataFrame(data) |
由字典、list、NumPy 陣列等建立 |
df.head() / df.tail() |
觀察前/後幾筆資料 |
df.info() |
顯示欄位型別與缺失值概況 |
df.describe() |
數值欄位的統計摘要 |
import pandas as pd
import numpy as np
# 由字典建立 DataFrame
data = {
"日期": pd.date_range("2023-01-01", periods=5, freq="D"),
"商品": ["A", "B", "A", "C", "B"],
"銷售額": [1200, 850, 950, 430, 770],
"庫存": [30, 45, 28, 50, 40]
}
df = pd.DataFrame(data)
print(df.head())
print("\n欄位資訊:")
df.info()
重點:
pd.date_range可直接產生時間序列,對於時間序列分析非常實用。
2️⃣ 資料選取(Selection)
2.1 依欄位名稱選取
# 取出單一欄位 → Series
sales = df["銷售額"]
# 同時取出多個欄位 → DataFrame
subset = df[["日期", "銷售額"]]
2.2 依列條件篩選(Boolean Indexing)
# 篩選商品為 "A" 且銷售額 > 900 的資料
filtered = df[(df["商品"] == "A") & (df["銷售額"] > 900)]
print(filtered)
2.3 使用 .loc 與 .iloc
| 方法 | 說明 |
|---|---|
df.loc[row_label, col_label] |
以 標籤(label)選取 |
df.iloc[row_index, col_index] |
以 位置(integer)選取 |
# 使用 .loc 依標籤選取第 2~4 列、"商品" 與 "庫存" 欄位
selected = df.loc[1:3, ["商品", "庫存"]]
print(selected)
# 使用 .iloc 依位置選取第 0、2 列與第 1、3 欄位
selected2 = df.iloc[[0, 2], [1, 3]]
print(selected2)
3️⃣ 新增、刪除與變更欄位
# 新增計算欄位:單位售價 = 銷售額 / 庫存
df["單位售價"] = df["銷售額"] / df["庫存"]
# 刪除欄位:使用 drop
df = df.drop(columns=["庫存"])
# 重新命名欄位
df = df.rename(columns={"單位售價": "售價 (元/件)"})
print(df)
小技巧:
assign()可在不改變原始 DataFrame 的情況下產生新欄位,適合串接多個操作。
df2 = df.assign(毛利=lambda x: x["銷售額"] * 0.2)
print(df2)
4️⃣ 缺失值處理(Missing Data)
# 假設在 "銷售額" 欄位加入缺失值
df.loc[2, "銷售額"] = np.nan
print(df)
# 方法一:直接刪除含缺失值的列
df_dropna = df.dropna(subset=["銷售額"])
# 方法二:填補缺失值(以平均值填補)
mean_sales = df["銷售額"].mean()
df_fillna = df["銷售額"].fillna(mean_sales)
df["銷售額"] = df_fillna
print(df)
注意:
dropna會回傳新的 DataFrame,除非使用inplace=True,否則原始資料不會被改變。
5️⃣ 資料聚合與分組(GroupBy)
# 以商品分組,計算每組的總銷售額與平均單位售價
grouped = df.groupby("商品").agg({
"銷售額": "sum",
"售價 (元/件)": "mean"
}).reset_index()
print(grouped)
5.1 多層次分組
# 加入日期月份作為第二層分組
df["月份"] = df["日期"].dt.month
multi_group = df.groupby(["商品", "月份"]).agg({
"銷售額": ["sum", "mean"],
"售價 (元/件)": "max"
})
print(multi_group)
常見陷阱與最佳實踐
| 陷阱 | 可能的結果 | 建議的做法 |
|---|---|---|
直接修改原始 DataFrame(忘記 inplace=False) |
造成不可預期的資料變動 | 盡量使用方法返回新物件,或明確設定 inplace=True |
使用 df.append() 逐筆加入 |
效能極差(O(n²)) | 改用一次性 pd.concat([df, new_rows]) |
| 忽略資料型別(例如日期被視為字串) | 失去時間序列功能 | 讀取時使用 parse_dates,或手動 pd.to_datetime() |
**布林索引中使用 &、` |
` 時忘記加括號** | 產生 ValueError: The truth value of a Series is ambiguous |
| 分組聚合後欄位名稱變成多層索引 | 後續存取不直觀 | 使用 agg(...).reset_index() 或 rename_axis(None, axis=1) 重新命名 |
最佳實踐小結
- 先檢查資料型別:
df.dtypes,確保數值、時間、類別欄位正確。 - 避免鏈式賦值警告:如
df['col'][mask] = value,改用df.loc[mask, 'col'] = value。 - 使用向量化運算:盡量避免
for迴圈,pandas 內建的運算速度更快。 - 記得釋放記憶體:大型資料集完成處理後,可使用
del df與gc.collect()。
實際應用場景
| 場景 | 典型操作 | 為何使用 pandas |
|---|---|---|
| 銷售報表自動化 | 讀取多個 CSV、合併、彙總、輸出 Excel | 支援多種檔案格式、快速分組聚合 |
| 金融時間序列分析 | 下載股票資料、計算移動平均、缺失值補齊 | 強大的時間索引 (DatetimeIndex) 與重抽樣功能 |
| 客戶行為分群 | 依屬性分組、計算 KPI、標籤化 | groupby + apply 可靈活自訂聚合邏輯 |
| 機器學習前的特徵工程 | 缺失值填補、類別編碼、特徵縮放 | 與 scikit-learn Pipeline 無縫結合 |
| 資料庫 ETL | 從 MySQL 讀取 → 轉換 → 匯入 PostgreSQL | read_sql, to_sql 直接對接 DB,減少中間檔案 |
範例:將每日銷售資料匯入資料庫,並自動產生每月彙總表
import sqlalchemy
# 建立資料庫連線
engine = sqlalchemy.create_engine("postgresql://user:pwd@localhost:5432/salesdb")
# 讀取 CSV 並寫入資料表
df_monthly = pd.read_csv("sales_2023_Jan.csv")
df_monthly.to_sql("daily_sales", con=engine, if_exists="append", index=False)
# 產生每月彙總
summary = pd.read_sql("""
SELECT DATE_TRUNC('month', 日期) AS month,
商品,
SUM(銷售額) AS total_sales
FROM daily_sales
GROUP BY month, 商品
ORDER BY month
""", con=engine)
print(summary.head())
總結
- pandas DataFrame 是 Python 資料處理的核心工具,掌握其建立、選取、變更、缺失值處理與分組聚合等操作,能大幅提升日常工作的效率。
- 在實務開發中,避免常見陷阱(如鏈式賦值、低效的逐筆加入)與 遵循最佳實踐(向量化、明確資料型別)是保證程式穩定與效能的關鍵。
- 透過本文的範例,你可以快速將 CSV、資料庫或 API 取得的原始資料,轉換成可直接用於報表、分析或機器學習的結構化資料。
希望這篇 pandas DataFrame 操作 的教學能成為你在資料處理路上可靠的參考手冊,祝你寫程式順利、資料分析得心應手!