本文 AI 產出,尚未審核

Python 資料處理:groupbymergepivot 完全指南


簡介

在日常的資料分析與商業應用中,資料整理往往是最耗時、也是最關鍵的工作。
即使有了乾淨的資料集,若無法快速彙總、合併或重新排列表格結構,我們仍無法從中抽取有價值的資訊。

pandas 作為 Python 生態系最常用的資料處理套件,提供了三個核心工具:

  • groupby – 依某些欄位分組並執行聚合運算
  • merge – 依鍵值把多個 DataFrame 合併在一起,類似資料庫的 JOIN
  • pivot / pivot_table – 重新塑形,將長條資料轉成寬表或產生交叉表

掌握這三個技巧,您就能在 資料清洗、探索性分析、報表製作 等階段大幅提升效率。本文將以實務為導向,從概念說明到常見陷阱,一步步帶您玩轉 groupbymergepivot


核心概念

1. groupby – 先分組再聚合

groupby 的基本流程可以想像成三個步驟:

  1. 分組 (Split):根據一或多個欄位將資料切分成多個子集合。
  2. 套用函式 (Apply):對每個子集合執行聚合、過濾或轉換。
  3. 合併結果 (Combine):將每個子集合的結果彙總成新的 DataFrame。

1.1 基本範例

import pandas as pd

# 建立測試資料
df = pd.DataFrame({
    '日期': pd.date_range('2024-01-01', periods=6, freq='D'),
    '產品': ['A', 'B', 'A', 'B', 'A', 'B'],
    '銷售量': [10, 20, 15, 25, 12, 18],
    '收入': [100, 200, 150, 250, 120, 180]
})

# 依「產品」分組,計算銷售量總和與收入平均值
result = df.groupby('產品').agg({
    '銷售量': 'sum',
    '收入': 'mean'
}).reset_index()

print(result)

輸出

  產品  銷售量    收入
0  A   37  123.33
1  B   63  210.00

重點agg() 可以同時對不同欄位指定不同的聚合函式,讓結果一次呈現。

1.2 多重分組與自訂聚合

# 依「產品」與「日期」的月份分組,計算每日銷售量的最大值與最小值
df['月份'] = df['日期'].dt.month
multi_grp = df.groupby(['產品', '月份']).agg({
    '銷售量': ['max', 'min'],
    '收入': 'sum'
})

# 為欄位重新命名
multi_grp.columns = ['銷售量_最大', '銷售量_最小', '收入總和']
multi_grp = multi_grp.reset_index()

print(multi_grp)

說明

  • groupby(['產品', '月份']) 會產生二層索引。
  • 使用 列表 方式指定多個聚合函式(['max', 'min']),最後再透過 columns 重新命名以提升可讀性。

1.3 transform – 保留原始形狀的分組計算

有時候我們想把分組後的統計值 回填 到原始 DataFrame,transform 正好符合需求:

# 計算每筆資料在其所屬「產品」的銷售量佔比
df['銷售量_佔比'] = df.groupby('產品')['銷售量'].transform(lambda x: x / x.sum())
print(df)

2. merge – 資料庫式的 JOIN

在實務上,我們常常需要把 不同來源(例如銷售紀錄、商品資訊、客戶資料)合併成一張完整的表格。pandas.merge() 提供了四種最常見的 JOIN 類型:

JOIN 類型 說明
inner 只保留兩表都有的鍵值(預設)
left 以左表為基礎,右表找不到則填 NaN
right 以右表為基礎,左表找不到則填 NaN
outer 兩表的鍵值全部保留,缺失的欄位以 NaN 填補

2.1 基本合併

# 商品資訊表
product = pd.DataFrame({
    '產品編號': [101, 102, 103],
    '產品名稱': ['手機', '筆電', '平板'],
    '類別': ['電子', '電子', '電子']
})

# 銷售紀錄表
sales = pd.DataFrame({
    '訂單編號': [1001, 1002, 1003],
    '產品編號': [101, 102, 104],
    '數量': [2, 1, 5]
})

# 內部合併:只保留兩表都有的「產品編號」
merged_inner = pd.merge(sales, product, on='產品編號', how='inner')
print(merged_inner)

輸出

   訂單編號  產品編號  數量  產品名稱   類別
0  1001   101   2   手機   電子
1  1002   102   1   筆電   電子

技巧:若欄位名稱不同,可分別使用 left_onright_on 指定。

2.2 多鍵合併與避免重複欄位

# 客戶表(含城市資訊)
customer = pd.DataFrame({
    '客戶編號': [1, 2, 3],
    '城市': ['台北', '新北', '台中']
})

# 訂單表(同時有客戶編號與城市,作為測試)
order = pd.DataFrame({
    '訂單編號': [2001, 2002, 2003],
    '客戶編號': [1, 2, 4],
    '城市': ['台北', '新北', '高雄'],
    '金額': [5000, 3000, 7000]
})

# 以「客戶編號」與「城市」同時作為鍵值合併(左合併)
merged_multi = pd.merge(order, customer, on=['客戶編號', '城市'], how='left')
print(merged_multi)

說明

  • 多鍵合併可確保 同一客戶在不同城市的紀錄 不會誤合。
  • 若兩表都有同名欄位但不作為鍵值,merge 會自動加上 _x_y 後綴,避免衝突。

2.3 indicator 參數 – 追蹤合併來源

# 加上 indicator,檢視每筆資料的合併狀態
merged_check = pd.merge(sales, product, on='產品編號', how='outer', indicator=True)
print(merged_check[['產品編號', '_merge']])

輸出

   產品編號      _merge
0    101       both
1    102       both
2    103  left_only
3    104 right_only

此功能在 資料清理 時特別有用,可快速找出缺失或多餘的鍵值。


3. pivot / pivot_table – 重新塑形與交叉表

pivot 能把「長條」資料(每筆紀錄只包含單一變數)轉成「寬表」形式,讓每個類別成為欄位。
若需要同時處理 重複索引缺失值,則使用功能更強大的 pivot_table

3.1 pivot 的簡單應用

# 銷售明細(長條格式)
sales_long = pd.DataFrame({
    '日期': pd.date_range('2024-01-01', periods=4, freq='D').repeat(3),
    '產品': ['A', 'B', 'C'] * 4,
    '銷售量': [5, 3, 2, 6, 4, 3, 7, 5, 4, 8, 6, 5]
})

# 以「日期」為索引,「產品」為欄位,聚合方式為 sum
sales_wide = sales_long.pivot(index='日期', columns='產品', values='銷售量')
print(sales_wide)

輸出

產品        A  B  C
日期                 
2024-01-01  5  3  2
2024-01-02  6  4  3
2024-01-03  7  5  4
2024-01-04  8  6  5

注意:若同一 index+columns 組合出現多筆資料,pivot 會拋出 ValueError

3.2 pivot_table 解決重複問題

# 加入重複資料
sales_long.loc[2, '銷售量'] = 10   # 同一天、同產品 A 出現兩筆

# 使用 pivot_table,指定聚合函式為 sum
sales_pt = sales_long.pivot_table(
    index='日期',
    columns='產品',
    values='銷售量',
    aggfunc='sum',
    fill_value=0   # 缺失值填 0
)

print(sales_pt)

說明

  • aggfunc 可以是 'sum''mean''max',甚至自訂函式。
  • fill_value 讓結果表格更易於後續計算(例如直接相加)。

3.3 多層索引與多變數

# 多變數範例:同時計算銷售量與收入的平均值
sales_detail = pd.DataFrame({
    '日期': pd.date_range('2024-01-01', periods=6, freq='D'),
    '產品': ['A', 'A', 'B', 'B', 'C', 'C'],
    '銷售量': [5, 6, 3, 4, 2, 3],
    '收入': [500, 600, 300, 400, 200, 300]
})

pt_multi = sales_detail.pivot_table(
    index='日期',
    columns='產品',
    values=['銷售量', '收入'],
    aggfunc='mean'
)

print(pt_multi)

結果MultiIndex(欄位同時有變數與產品),可使用 pt_multi['銷售量']['A'] 直接取出特定子表。


常見陷阱與最佳實踐

陷阱 說明 解決方法
groupby 產生的索引不易閱讀 groupby 後的結果會把分組欄位變成索引。 使用 .reset_index() 或在 agg 時直接指定 as_index=False
merge 產生重複欄位 兩表同名欄位且未指定為鍵值,會自動加上 _x/_y 事先 rename 欄位,或在 merge 後使用 df.filter/df.drop 清理。
pivot 無法處理重複索引 若同一 index+columns 出現多筆,拋錯。 改用 pivot_table,或先使用 groupby 先聚合。
缺失值的傳遞 groupbymergepivot 都會把 NaN 帶入結果,可能影響後續運算。 使用 fillna()dropna() 或在 agg 時指定 fill_value
效能問題 大型資料(>10^6 筆)頻繁 groupby+merge 會變慢。 - 先 篩選 必要欄位
- 使用 categorical 類型降低記憶體
- 若可行,改用 DaskPolars 等分散式框架。

最佳實踐小結

  1. 先思考資料流:先 groupby 聚合再 merge,往往比一次性合併後再聚合更有效率。
  2. 明確指定鍵值與欄位類型astype('category') 可顯著提升 groupbymerge 的速度。
  3. 善用 aggpivot_table 的多函式特性:一次完成多個統計指標,避免重複計算。
  4. 保留原始資料:在重要步驟前 df.copy(),以免不小心改變原始 DataFrame。

實際應用場景

場景 需求 使用工具 範例流程
銷售報表 按月份、產品類別統計銷售額與毛利 groupby + pivot_table 1. 讀入交易資料 2. groupby(['月份','類別']).agg({'銷售額':'sum','毛利':'mean'}) 3. pivot_table 產生交叉表供 Excel 匯出
客戶分群 合併客戶基本資訊與最近 6 個月的購買行為 merge(left join)+ groupby 1. 讀入 customerorder 2. merge(customer, order, on='客戶編號', how='left') 3. groupby('客戶編號').agg({'金額':'sum','訂單編號':'nunique'})
異常偵測 找出同一天、同產品的銷售量突增 groupby + transform 1. df['每日均值'] = df.groupby(['日期','產品'])['銷售量'].transform('mean') 2. df['異常'] = df['銷售量'] > df['每日均值'] * 3
市場調查 交叉分析不同地區、不同年齡層的產品偏好 pivot_table(多維度) pivot_table(index='地區', columns='年齡層', values='購買次數', aggfunc='sum', fill_value=0)
資料庫遷移 從多個 CSV 合併成單一事實表(Fact Table) 多次 merge(inner)+ groupby 去重 1. 讀入 sales.csv, product.csv, store.csv 2. 依主鍵 product_id, store_id 依序 merge 3. groupby(['order_id']).first() 產生唯一事實表

總結

  • groupby 是彙總與統計的核心,配合 aggtransform 能同時產出多種指標。
  • merge 為資料庫式的 JOIN,掌握 howindicator、多鍵合併等參數,可安全且高效地整合多源資料。
  • pivot / pivot_table 讓長條資料瞬間變寬,提供交叉表與多維度分析的利器;遇到重複索引時,pivot_table 是最好的備胎。

透過上述概念與實作範例,您已具備在 資料清理、探索性分析以及報表自動化 中運用 groupbymergepivot 的能力。建議在日常專案中,先以 小樣本驗證 再擴展至全量資料,並隨時檢查 記憶體與效能,才能真正把 Python 的資料處理力量發揮到極致。祝您在資料分析的路上玩得開心、寫程式更順!