Python案例实战:如何用Pandas做数据透视表(从入门到精通)
📚 目录导读
为什么需要数据透视?
在做数据分析时,我们经常需要从不同维度观察数据,不同地区、不同月份的销售额”或者“不同班级、不同科目的平均分”,Excel中的数据透视表功能强大,而Python的Pandas库提供了更灵活的pivot_table方法。

❓Q&A
Q:数据透视和普通分组有啥区别?
A:普通分组(groupby)只能按单一维度计算,而pivot_table支持行、列、数值三维交叉分析,并自动处理缺失值。
Pandas pivot_table核心参数解析
pandas.pivot_table(data, values, index, columns, aggfunc, fill_value, margins, margins_name)
| 参数 | 作用 | 必填 |
|---|---|---|
data |
DataFrame对象 | 是 |
values |
要计算的数值列 | 是 |
index |
行索引(分组维度) | 是 |
columns |
列维度(可选) | 否 |
aggfunc |
聚合函数(默认mean) | 否 |
fill_value |
填充缺失值 | 否 |
margins |
是否显示总计 | 否 |
❓Q&A
Q:aggfunc可以用哪些函数?
A:支持'sum', 'mean', 'count', 'max', 'min', 'std', 'median',甚至自定义函数,注意:如果传入字符串需用引号。
案例1:销售数据多维分析
假设我们有300条模拟销售数据(公司内部系统导出),包含字段:订单日期, 区域, 产品类别, 销售额。
步骤1:导入数据
import pandas as pd
import numpy as np
# 模拟销售数据(实际使用时替换为真实CSV)
np.random.seed(42)
dates = pd.date_range('2024-01-01', periods=300, freq='D')
data = {
'日期': np.random.choice(dates, 300),
'区域': np.random.choice(['华东', '华南', '华北', '西南'], 300),
'产品': np.random.choice(['手机', '电脑', '平板', '耳机'], 300),
'销售额': np.random.uniform(100, 5000, 300).round(2)
}
df = pd.DataFrame(data)
步骤2:创建基本透视表
# 分析:不同区域、不同产品的总销售额
pivot1 = pd.pivot_table(
df,
values='销售额',
index='区域',
columns='产品',
aggfunc='sum',
fill_value=0
)
print("各区域产品销售额透视表:")
print(pivot1)
输出效果(示例):
产品 耳机 电脑 平板 手机
区域
华东 23456.78 34567.89 45678.90 56789.01
华南 32109.87 21098.76 10987.65 98765.43
...
步骤3:添加时间维度
# 按月份和区域分析销售额
df['月份'] = df['日期'].dt.month
pivot2 = pd.pivot_table(
df,
values='销售额',
index='月份',
columns='区域',
aggfunc='mean',
margins=True,
margins_name='总计'
)
print("\n按月-区域平均销售额(含总计):")
print(pivot2)
❓Q&A
Q:为什么我的结果全是NaN?
A:检查values列是否有缺失值,或aggfunc选择不当,用fill_value=0填充后,就可以看到完整表格。
案例2:学生成绩交叉统计
假设有学校教务系统导出的成绩表:班级, 科目, 姓名, 成绩。
步骤1:实战数据准备
# 模拟学生成绩数据
classes = ['A班', 'B班', 'C班']
subjects = ['语文', '数学', '英语']
students = [f'学生{i}' for i in range(1, 31)]
df_grade = pd.DataFrame({
'班级': np.random.choice(classes, 90),
'科目': np.random.choice(subjects, 90),
'姓名': np.random.choice(students, 90),
'成绩': np.random.randint(60, 100, 90)
})
步骤2:多级索引透视
# 透视:班级为行,科目为列,显示平均分和最高分
pivot_grade = pd.pivot_table(
df_grade,
values='成绩',
index=['班级'], # 行索引
columns=['科目'], # 列索引
aggfunc={'成绩': ['mean', 'max']}, # 同时计算均值和最大值
fill_value=0
)
print("\n学生成绩透视(双聚合):")
print(pivot_grade)
步骤3:优化显示格式
# 重命名列层级
pivot_grade.columns = ['_'.join(col).strip() for col in pivot_grade.columns.values]
pivot_grade.columns = ['语文均分', '语文最高', '数学均分', '数学最高', '英语均分', '英语最高']
print("\n优化后:")
print(pivot_grade)
❓Q&A
Q:不同聚合函数可以分列指定吗?
A:可以!如本案例所示,aggfunc传入字典即可为不同值列指定不同函数(虽然这里都是成绩列,但写法通用),但注意字典的key要匹配values参数。
案例3:电商用户行为透视
假设有电商平台订单表:用户ID, 购买月份, 订单金额, 是否会员。
# 模拟电商数据
df_shop = pd.DataFrame({
'用户ID': np.random.randint(1001, 1101, 500),
'购买月份': np.random.choice(['1月','2月','3月','4月'], 500),
'订单金额': np.random.uniform(50, 500, 500).round(2),
'是否会员': np.random.choice(['是','否'], 500, p=[0.6,0.4])
})
实战:会员与非会员的消费对比
pivot_shop = pd.pivot_table(
df_shop,
values='订单金额',
index=['购买月份'],
columns=['是否会员'],
aggfunc=['count', 'mean', 'sum'],
margins=True,
margins_name='汇总'
)
print("\n会员与非会员消费行为透视:")
print(pivot_shop)
❓Q&A
Q:如果columns参数有多个值怎么处理?
A:传入列表即可生成多层列索引,例如columns=['是否会员','购买月份']就会先生成会员分类,再内嵌月份。
常见问题与性能优化
❓Q&A
Q:数据量很大(百万级)时卡顿怎么办?
A:建议按此优先顺序优化:
- 先过滤不必要的数据(
df[df['字段'] > 阈值]) - 用
categorical类型优化分类变量内存 - 考虑分块处理(
chunksize参数) - 改用
crosstab(专门处理频率统计,速度更快)
Q:pivot和pivot_table有什么区别?
A:pivot要求数据必须唯一(无重复),否则报错;pivot_table自动处理重复值(按聚合函数计算),日常数据分析应优先使用pivot_table。
小技巧:透视表转Excel美化
# 将透视结果保存到带格式的Excel
with pd.ExcelWriter('report.xlsx', engine='xlsxwriter') as writer:
pivot.to_excel(writer, sheet_name='透视结果')
workbook = writer.book
worksheet = writer.sheets['透视结果']
# 添加条件格式(突出大于5000的单元格)
worksheet.conditional_format('B2:Z100', {'type': 'cell', 'criteria': '>', 'value': 5000, 'format': workbook.add_format({'bg_color': '#FFC7CE'})})
结语与进阶学习
通过以上三个真实场景案例,能看到Pandas数据透视不仅能快速生成报表,还能通过参数灵活组合实现复杂分析,建议将以下资料加入收藏夹:
- Pandas官方文档(pandas.pydata.org)的
pivot_table部分 - 《利用Python进行数据分析》第9章
- 开源项目:pandas-profiling(自动生成探索性分析报告)
先理解业务需求,再设计透视表的行、列、值三维结构,当你面对杂乱的数据时,不妨先用df.info()查看数据类型,再通过df.describe()初步了解分布,最后用透视表深入挖掘规律。
最后留一个练习:找一份真实的数据集(比如Kaggle上的超市销售数据),尝试用pivot_table分析“不同支付方式在周末与工作日的销售额差异”,你会得到意想不到的业务洞察。