Pandas 樞紐分析表
樞紐分析表(Pivot Table)是一種強大的資料摘要工具,可以將資料重新組織成易於分析的格式。類似 Excel 中的樞紐分析表功能。
基本概念
樞紐分析表將資料從「長格式」轉換成「寬格式」,並進行聚合計算。
pivot_table()
基本用法
import pandas as pd
import numpy as np
df = pd.DataFrame({
'city': ['Taipei', 'Tokyo', 'Taipei', 'Tokyo', 'Taipei', 'Tokyo'],
'year': [2023, 2023, 2024, 2024, 2023, 2024],
'sales': [100, 200, 150, 250, 120, 280]
})
# 建立樞紐分析表
pivot = pd.pivot_table(df, values='sales', index='city', columns='year')
print(pivot)
year 2023 2024
city
Taipei 110.0 150.0
Tokyo 200.0 265.0
預設會使用 mean 作為聚合函數。
指定聚合函數
# 使用總和
pivot = pd.pivot_table(df, values='sales', index='city', columns='year', aggfunc='sum')
print(pivot)
year 2023 2024
city
Taipei 220 150
Tokyo 200 530
多種聚合函數
pivot = pd.pivot_table(df, values='sales', index='city', columns='year',
aggfunc=['sum', 'mean', 'count'])
print(pivot)
多個值欄位
df = pd.DataFrame({
'city': ['Taipei', 'Tokyo', 'Taipei', 'Tokyo'],
'year': [2023, 2023, 2024, 2024],
'sales': [100, 200, 150, 250],
'profit': [10, 20, 15, 25]
})
pivot = pd.pivot_table(df, values=['sales', 'profit'], index='city', columns='year')
print(pivot)
多層索引和欄位
df = pd.DataFrame({
'city': ['Taipei', 'Taipei', 'Tokyo', 'Tokyo'] * 2,
'category': ['A', 'B', 'A', 'B'] * 2,
'year': [2023] * 4 + [2024] * 4,
'sales': [100, 150, 200, 180, 120, 160, 220, 190]
})
pivot = pd.pivot_table(df, values='sales',
index=['city', 'category'],
columns='year')
print(pivot)
處理缺失值
# 用 0 填補缺失值
pivot = pd.pivot_table(df, values='sales', index='city', columns='year', fill_value=0)
加上邊際總計
pivot = pd.pivot_table(df, values='sales', index='city', columns='year',
aggfunc='sum', margins=True, margins_name='Total')
print(pivot)
year 2023 2024 Total
city
Taipei 220 150 370
Tokyo 200 530 730
Total 420 680 1100
pivot()
pivot() 是 pivot_table() 的簡化版,不進行聚合:
df = pd.DataFrame({
'city': ['Taipei', 'Tokyo', 'Seoul'],
'year': [2023, 2023, 2023],
'sales': [100, 200, 150]
})
# 每個 city-year 組合只能有一個值
pivot = df.pivot(index='city', columns='year', values='sales')
如果有重複的組合,pivot() 會報錯,此時應使用 pivot_table()。
反向操作:melt()
將「寬格式」轉回「長格式」:
# 原始寬格式
df_wide = pd.DataFrame({
'city': ['Taipei', 'Tokyo'],
'2023': [100, 200],
'2024': [150, 250]
})
# 轉成長格式
df_long = df_wide.melt(id_vars='city', var_name='year', value_name='sales')
print(df_long)
city year sales
0 Taipei 2023 100
1 Tokyo 2023 200
2 Taipei 2024 150
3 Tokyo 2024 250
crosstab():交叉表
crosstab() 專門用於計算交叉頻率表:
df = pd.DataFrame({
'gender': ['M', 'F', 'M', 'F', 'M'],
'city': ['Taipei', 'Tokyo', 'Taipei', 'Taipei', 'Tokyo']
})
# 計算頻率
ct = pd.crosstab(df['gender'], df['city'])
print(ct)
city Taipei Tokyo
gender
F 1 1
M 2 1
# 顯示百分比
ct = pd.crosstab(df['gender'], df['city'], normalize='all')
# 按列百分比
ct = pd.crosstab(df['gender'], df['city'], normalize='columns')
# 按行百分比
ct = pd.crosstab(df['gender'], df['city'], normalize='index')
# 加上邊際總計
ct = pd.crosstab(df['gender'], df['city'], margins=True)
實際應用
銷售報表
df = pd.DataFrame({
'date': pd.date_range('2024-01-01', periods=12, freq='M'),
'product': ['A', 'B', 'A', 'B'] * 3,
'region': ['North', 'North', 'South', 'South'] * 3,
'sales': [100, 150, 120, 180, 130, 160, 140, 190, 150, 170, 160, 200]
})
# 按產品和區域的月銷售報表
df['month'] = df['date'].dt.month
pivot = pd.pivot_table(df, values='sales',
index=['product', 'region'],
columns='month',
aggfunc='sum',
fill_value=0)
學生成績表
df = pd.DataFrame({
'student': ['Alice', 'Bob', 'Alice', 'Bob', 'Alice', 'Bob'],
'subject': ['Math', 'Math', 'English', 'English', 'Science', 'Science'],
'score': [90, 85, 88, 92, 95, 78]
})
# 轉成成績表格式
pivot = df.pivot(index='student', columns='subject', values='score')
print(pivot)
subject English Math Science
student
Alice 88 90 95
Bob 92 85 78
計算轉換率
df = pd.DataFrame({
'source': ['Google', 'Facebook', 'Google', 'Facebook'] * 2,
'action': ['view', 'view', 'click', 'click', 'view', 'click', 'view', 'click'],
'count': [1000, 800, 100, 50, 1200, 120, 900, 60]
})
pivot = pd.pivot_table(df, values='count', index='source', columns='action', aggfunc='sum')
pivot['conversion_rate'] = pivot['click'] / pivot['view']
print(pivot)