一句话总结
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 堆叠与取消堆叠 继续整理。