Pandas pivot_table 从参数到电商实战:聚合与多维透视完全指南
数据分析中,面对原始流水数据,需要按多个维度分组汇总出二维报表。Pandas 的 pivot_table 能将分组、聚合、重塑三步合并为一行代码,是生成报表的最直接工具。本文从参数详解、基础示例、真实场景、横向对比到综合实战,完整演示 pivot_table 的核心用法。核心参数说明
pivot_table 的签名为:
pandas.pivot_table(
data,
values=None,
index=None,
columns=None,
aggfunc='mean',
fill_value=None,
margins=False,
dropna=True,
margins_name='All',
observed=False,
sort=True
)
每个参数的含义和注意事项:
- data:DataFrame,必填。
- values:str 或 list,要聚合的数值列;省略则对所有数值列聚合。
- index:str 或 list,行分组字段,传列表形成多层行索引。
- columns:str 或 list,列分组字段,传列表形成多层列索引。
- aggfunc:func / list / dict,默认 'mean',支持字符串、函数、列表、字典,字典语法可对不同列使用不同聚合函数。
- fill_value:标量,聚合后产生的 NaN 用此值填充。
- margins:bool,是否添加行列汇总(小计/总计)。
- dropna:bool,聚合前丢弃全为 NaN 的列。注意与 fill_value 顺序:先丢后填。
- margins_name:str,汇总行/列标签,可改为“合计”或“总计”。
- observed:bool,仅对 Categorical 类型有效,建议 pandas 2.2+ 设为 True 只显示实际出现的组合,避免产生全零行。
- sort:bool,结果是否排序(v1.3.0 新增)。
基础用法演示
先准备示例数据:
import pandas as pd
import numpy as np
df = pd.DataFrame({
"A": ["foo", "foo", "foo", "foo", "foo", "bar", "bar", "bar", "bar"],
"B": ["one", "one", "one", "two", "two", "one", "one", "two", "two"],
"C": ["small", "large", "large", "small", "small", "large", "small", "small", "large"],
"D": ,
"E":
})
最基础用法:按 A、B 分行,按 C 分列,对 D 列求和:
table = pd.pivot_table(df, values='D', index=['A', 'B'],
columns=['C'], aggfunc="sum", fill_value=0)
print(table)
输出中原本缺失的组合(如 foo/two/large)用 fill_value=0 填充为 0。
对不同列使用不同聚合函数:
table = pd.pivot_table(df, values=['D', 'E'], index=['A', 'C'],
aggfunc={'D': 'mean', 'E': ['min', 'max', 'mean']})
print(table)
结果列变为多层索引,E 列下挂三个子列。
真实场景实战
1. 销售报表
按季度和地区汇总销售额与利润:
data = {
'地区': ['华东', '华东', '华北', '华北', '华南', '华南'],
'产品': ['A', 'B', 'A', 'B', 'A', 'B'],
'季度': ,
'销售额': ,
'利润':
}
df_sales = pd.DataFrame(data)
pivot = pd.pivot_table(
data=df_sales,
values=['销售额', '利润'],
index='季度',
columns='地区',
aggfunc='sum',
fill_value=0,
margins=True,
margins_name='总计'
)
print(pivot)
b]2. 时间维度多层索引
将“地区”和“月份”作为行索引,产品作为列:
df['月份'] = df['日期'].dt.month
pivot = pd.pivot_table(
data=df,
index=['地区', '月份'],
columns='产品',
values='销售额',
aggfunc='sum'
)
# 用 xs 切片
print(pivot.xs('华东', level='地区'))
3. 用户行为多函数聚合
同时查看总访问量和人均次数:
pivot = pd.pivot_table(
data=df_user,
index='用户等级',
columns='访问渠道',
values='访问次数',
aggfunc=['sum', 'mean'],
fill_value=0
)
高级技巧
自定义聚合函数:用 lambda 计算极差(最大值减最小值):
pivot = pd.pivot_table(df, values='D', index='A',
aggfunc=lambda x: x.max() - x.min())
同时使用多个内置函数:
pivot = pd.pivot_table(df, values='D', index='A',
aggfunc=['sum', 'mean', 'count', np.std])
扁平化多层列名:当 aggfunc 为列表/字典时,列索引变为 MultiIndex,可用列表推导压平:
pivot.columns = ['_'.join(col).strip() for col in pivot.columns.values]
链式操作:透视结果是标准 DataFrame,可直接接 reset_index、sort_values、query:
result = (
pd.pivot_table(df, values='销售额', index='地区', aggfunc='sum')
.reset_index()
.sort_values('销售额', ascending=False)
.query('销售额 > 100000')
)
相近方法对比
| 方法 | 支持重复值 | 支持聚合 | 输出格式 | 适用场景 |
|------|-----------|---------|---------|---------|
| pivot() | ❌ | ❌ | 宽格式 | 数据唯一,纯重塑 |
| pivot_table() | ✅ | ✅ 灵活 | 宽格式 | 汇总报表、多维分析 |
| groupby() | ✅ | ✅ 灵活 | 长格式 | 分组统计,输出灵活 |
| crosstab() | ✅ | ✅ 默认频次 | 宽格式 | 交叉频次统计 |
经验:生成“行×列”二维汇总统首选 pivot_table;仅单列分组用 groupby 更简洁;问卷交叉分析用 crosstab。
综合实战:电商订单分析
模拟 200 条订单数据,按地区+季度为行、产品类别为列,销售额求和、利润求均值,并添加总计:
import pandas as pd
import numpy as np
np.random.seed(42)
n = 200
df = pd.DataFrame({
'地区': np.random.choice(['华东', '华北', '华南', '西部'], n),
'产品类别': np.random.choice(['电子', '服装', '食品'], n),
'季度': np.random.choice(, n),
'销售额': np.random.randint(1000, 50000, n),
'利润': np.random.randint(100, 10000, n),
'订单数': np.random.randint(1, 100, n)
})
pivot = pd.pivot_table(
data=df,
values=['销售额', '利润'],
index=['地区', '季度'],
columns='产品类别',
aggfunc={'销售额': 'sum', '利润': 'mean'},
fill_value=0,
margins=True,
margins_name='汇总'
)
# 扁平化列名
pivot.columns = ['_'.join(col) for col in pivot.columns]
print(pivot.head(10))
# 单独看华东的数据
print(pivot.xs('华东', level='地区'))
总结
pivot_table 将分组、聚合、重塑压缩为声明式代码。核心习惯:用 index/columns 控制维度,aggfunc 字典处理异构聚合,margins=True 自动加总计,fill_value 填充空缺,结果是标准 DataFrame 可继续链式操作。多跑真实数据,很快就能掌握。
Re: Pandas pivot_table 从参数到电商实战:聚合与多维透视完全指南
楼主整理得很详细,从参数到场景实战都很清晰,尤其是对不同列使用不同聚合函数那段,之前一直没注意到 `aggfunc` 传字典的写法,学到了。 想请教一个细节:在实际电商数据中,如果 `index` 和 `columns` 里都有很多分类字段(比如地区、品类、渠道),生成的透视表列数会爆炸,有没有什么方法在 `pivot_table` 之后快速筛选出需要的子表?目前我都是用 `xs` 或 `loc` 做切片,但多层索引切起来容易搞混。或者有没有更优雅的扁平化方式?感谢分享!Re: Pandas pivot_table 从参数到电商实战:聚合与多维透视完全指南
写得非常详细,参数解释和场景示例都很清楚,特别是对不同列用不同聚合函数和实际销售报表的案例,特别实用。之前我每次用multi-level columns时都容易搞混,看了你的多层索引和xs切片那段,终于理清了。有个小问题想请教:在真实场景中,如果index和columns里都有缺失值,pivot_table默认会怎么处理?dropna=True是先剔除所有包含NaN的行再聚合吗?谢谢。Re: Pandas pivot_table 从参数到电商实战:聚合与多维透视完全指南
感谢楼主的详细教程!之前用 pivot_table 经常记不清参数,你这篇把每个参数都拆开讲清楚,还配了电商实战例子,特别实用。我平时做销售报表时也喜欢用 margins 加总计,但有时对不同列选不同 aggfunc 会把多级列索引搞乱,你给的字典写法刚好解决了这个痛点。另外想请教一下,如果数据里 index 或 columns 的字段中有 NaN,fill_value 在聚合前和聚合后的处理顺序有没有什么坑?希望楼主再讲讲这个细节。
页:
[1]