一句话总结

pivot() 用于无聚合的重塑(要求索引唯一),pivot_table() 是带聚合的透视表(可处理重复值),是数据分析中最常用的工具之一。

1. pivot() — 简单透视

将长格式数据重新排列为宽格式。不进行聚合,要求原数据中 (index, columns) 组合唯一。

基本语法

DataFrame.pivot(*, index=_NoDefault.no_default, columns=_NoDefault.no_default,
                values=_NoDefault.no_default)

参数说明

参数说明
index用作新 DataFrame 行索引的列名或列名列表
columns用作新 DataFrame 列索引的列名或列名列表
values要填充的列名或列名列表(可选;不指定时使用其余所有列)

示例:基本用法

import pandas as pd
 
df = pd.DataFrame({
    'date': ['2024-01-01', '2024-01-01', '2024-01-02', '2024-01-02'],
    'city': ['北京', '上海', '北京', '上海'],
    'temp': [3, 8, 1, 6]
})
 
pivoted = df.pivot(index='date', columns='city', values='temp')
print(pivoted)
# city        北京  上海
# date
# 2024-01-01    3    8
# 2024-01-02    1    6

示例:多列作为 values

df2 = df.assign(humidity=[60, 70, 55, 65])
pivoted_multi = df2.pivot(index='date', columns='city', values=['temp', 'humidity'])
# 结果为两层列索引:temp / humidity → 北京 / 上海

示例:不指定 values(使用其余列)

# 将所有未用列的值都作为透视结果
pivoted_all = df.pivot(index='date', columns='city')

示例:多列作为 index

df3 = df.assign(year=[2023, 2023, 2024, 2024])
pivoted_multi_idx = df3.pivot(index=['year', 'date'], columns='city', values='temp')

重复索引错误

若 (index, columns) 组合存在重复值,pivot() 会抛出 ValueError: Index contains duplicate entries。此时应使用 pivot_table() 进行聚合。

2. pivot_table() — 数据透视表

在 pivot() 基础上增加了聚合能力,可处理重复值,功能上等价于 groupby + unstack。

基本语法

DataFrame.pivot_table(*, values=None, index=None, columns=None,
                      aggfunc='mean', fill_value=None, margins=False,
                      dropna=True, margins_name='All', observed=False,
                      sort=True)

参数详解

参数说明
values需要聚合的列名或列名列表;不指定时使用所有数值列
index行分组键:列名 / list / 可调用对象 / Grouper
columns列分组键:列名 / list
aggfunc聚合函数或函数列表,默认 'mean'。常用:'sum'、'count'、'min'、'max'、'median'、np.mean、自定义函数、dict 指定不同列
fill_value填充缺失值的标量
margins是否添加总计行/列,默认 False
margins_name总计行列的名称,默认 'All'
observed仅在 aggfunc='count' 等场景生效;分类数据分组时是否只显示已出现的类别,与 十六、分组与聚合 的 observed 一致
sort是否对结果排序,默认 True
dropna是否忽略全为 NaN 的列,默认 True

示例:基本透视表

sales = pd.DataFrame({
    'region': ['北区', '北区', '南区', '南区', '北区', '南区'],
    'product': ['A', 'B', 'A', 'B', 'A', 'A'],
    'amount': [100, 200, 150, 250, 300, 120]
})
 
pt = sales.pivot_table(index='region', columns='product', values='amount',
                       aggfunc='sum')
print(pt)
# product      A     B
# region
# 北区       400  200.0
# 南区       270  250.0

示例:aggfunc 使用列表 — 多重聚合

pt_multi_agg = sales.pivot_table(index='region', columns='product', values='amount',
                                 aggfunc=['sum', 'mean', 'count'])

示例:aggfunc 使用 dict — 不同列不同聚合

sales2 = sales.assign(quantity=[5, 10, 4, 12, 20, 8])
pt_dict = sales2.pivot_table(index='region', columns='product',
                             values={'amount': 'sum', 'quantity': 'mean'})

示例:margins 总计

pt_margins = sales.pivot_table(index='region', columns='product', values='amount',
                               aggfunc='sum', margins=True, margins_name='总计')
# 自动添加行/列的"总计"

示例:fill_value 填充缺失

pt_filled = sales.pivot_table(index='region', columns='product', values='amount',
                              aggfunc='sum', fill_value=0)
# 不存在的组合显示 0 而非 NaN

示例:多级行列

pt_multi = sales2.pivot_table(index=['region', 'product'], columns='...',
                              values='amount', aggfunc='sum')

3. pivot() vs pivot_table() 对比

维度pivot()pivot_table()
聚合❌ 不聚合✅ 聚合(默认 mean)
重复值❌ 报错✅ 自动聚合处理
缺失值保留 NaN可用 fill_value 填充
总计行列❌✅ margins
本质重塑groupby + 重塑
适用场景索引唯一的长表转宽表含重复键的统计汇总

4. 实际案例:销售数据汇总

# 构建包含重复键的销售明细
orders = pd.DataFrame({
    'date':    ['2024-01-01'] * 4 + ['2024-01-02'] * 4,
    'city':    ['北京', '北京', '上海', '上海', '北京', '北京', '上海', '上海'],
    'category':['手机', '电脑', '手机', '电脑', '手机', '电脑', '手机', '电脑'],
    'sales':   [1200, 2500, 980, 3100, 1500, 2200, 1100, 2800],
    'qty':     [3, 1, 2, 2, 4, 1, 3, 2]
})
 
# 二维透视:城市 × 品类 的总销售额
summary = orders.pivot_table(index='city', columns='category',
                             values='sales', aggfunc='sum',
                             margins=True, margins_name='合计')
print(summary)
 
# 三维透视:日期为行,城市为列,品类聚合
summary2 = orders.pivot_table(index='date', columns='city',
                              values='sales', aggfunc='sum')

实用建议

  • 聚合需求不明确时,先用 aggfunc='sum' 看总量,再按需切换其他函数。
  • 出现同一维度多指标时,将 values 设为列表,结果会生成两层列索引,可配合 15.1 堆叠与取消堆叠 继续整理。

相关笔记