Python多组groupby条形图合并教程
时间:2025-10-26 22:33:36 250浏览 收藏
本文详细介绍了如何利用Python的Pandas和Matplotlib库,巧妙地将基于相同分组但聚合方式不同的数据(如平均值与总和)合并,并以并排条形图的形式进行可视化展示。针对直接使用`groupby().agg().plot.barh()`难以实现多聚合结果并排展示的问题,提出了通过数据框合并和Matplotlib子图功能,配合精细的轴标签设置的解决方案。文章通过实例演示了如何独立聚合数据、合并聚合结果,并利用`barh()`函数调整条形位置和宽度,最终生成清晰直观的对比图,有效提升数据分析报告的可读性和专业性,是数据分析与可视化中一项实用技巧。

在数据分析工作中,我们经常需要对数据进行分组聚合,并对不同聚合结果进行比较。例如,我们可能需要同时查看某个类别下数据的平均值和总和。虽然Pandas的groupby().agg().plot.barh()可以方便地生成单个聚合的条形图,但要将两个或更多聚合结果并排展示在一个图中,则需要更灵活的方法。本教程将指导您如何通过数据合并和Matplotlib的强大功能实现这一目标。
问题场景
假设我们有一个名为day_df的数据集,其中包含年份(yr)、季节(season)和天气情况(weathersit)等分类变量,以及一个数值变量cnt(计数)。我们希望同时可视化按这三个分类变量分组后的cnt的平均值和总和。
直接尝试将两个groupby().agg().plot.barh()的结果合并到一个图中通常会失败,因为它们生成的是独立的图表。此外,如果尝试手动使用plt.bar()或plt.barh(),可能会遇到索引对齐和标签设置的挑战,尤其是在处理多层索引时。
解决方案核心思路
解决此问题的关键在于:
- 独立聚合数据: 分别计算每个分组的平均值和总和。
- 合并聚合结果: 将这些独立的聚合结果合并到一个Pandas DataFrame中。
- 使用Matplotlib绘制: 利用Matplotlib的barh()(或bar())函数在同一个坐标轴上绘制合并后的数据,并通过调整条形的位置和宽度实现并排显示。
详细步骤与代码示例
1. 准备数据并进行分组聚合
首先,我们需要对原始数据进行两次分组聚合,一次计算cnt的平均值,另一次计算cnt的总和。为了方便后续合并,聚合后需要使用reset_index()将多层索引转换为普通列。
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
# 假设 day_df 是您的原始数据框
# 为了教程的可运行性,这里创建一个模拟数据框
data = {
'yr': np.random.choice([0, 1], 100),
'season': np.random.choice([1, 2, 3, 4], 100),
'weathersit': np.random.choice([1, 2, 3], 100),
'cnt': np.random.randint(100, 1000, 100)
}
day_df = pd.DataFrame(data)
# 计算每个分组的平均值并重置索引
day_mean_dataframe = day_df.groupby(by=["yr", "season", "weathersit"]).agg({"cnt": "mean"}).reset_index()
# 计算每个分组的总和并重置索引
day_sum_dataframe = day_df.groupby(by=["yr", "season", "weathersit"]).agg({"cnt": "sum"}).reset_index()
print("平均值数据框(部分):")
print(day_mean_dataframe.head())
print("\n总和数据框(部分):")
print(day_sum_dataframe.head())2. 合并聚合后的数据框
接下来,我们将这两个聚合后的数据框合并。由于它们共享相同的分组键(yr, season, weathersit),我们可以使用pd.merge()函数进行内连接。为了区分聚合结果,我们使用suffixes参数为cnt列添加后缀。
# 合并两个数据框
merged_df = pd.merge(day_mean_dataframe, day_sum_dataframe,
on=["yr", "season", "weathersit"],
suffixes=('_mean', '_sum'))
print("\n合并后的数据框(部分):")
print(merged_df.head())merged_df现在包含每个分组的cnt_mean和cnt_sum两列,方便我们进行统一绘图。
3. 使用Matplotlib绘制并排条形图
现在,我们可以使用Matplotlib的barh()函数来绘制水平并排条形图。
# 创建图和子图对象
fig, ax = plt.subplots(figsize=(12, 8)) # 调整图大小以适应更多标签
# 为每个分组创建一个位置数组
r1 = np.arange(len(merged_df))
height1 = 0.4 # 设置条形的高度,用于 barh
# 绘制平均值条形
ax.barh(r1, merged_df["cnt_mean"], height=height1, label='平均值 (Mean)', color='skyblue')
# 绘制总和条形,将其位置偏移,实现并排效果
ax.barh(r1 + height1, merged_df["cnt_sum"], height=height1, label='总和 (Sum)', color='lightcoral')
# 设置Y轴刻度标签
# 将刻度放在两个条形之间
ax.set_yticks(r1 + height1 / 2)
# 生成可读性强的Y轴标签,结合所有分组键
ax.set_yticklabels([f'年份: {row.yr}, 季节: {row.season}, 天气: {row.weathersit}'
for _, row in merged_df.iterrows()])
# 添加图例、轴标签和标题
ax.set_xlabel('计数 (Count)')
ax.set_ylabel('分组类别 (Group Categories)')
ax.set_title('不同分组下计数平均值与总和的对比')
ax.legend()
# 调整布局,防止标签重叠
plt.tight_layout()
plt.show()代码说明与注意事项
- reset_index()的重要性: 在groupby().agg()之后调用reset_index()是关键一步。它将多层索引转换为普通列,使得后续的pd.merge()操作更加直接,并且在设置yticklabels时也能方便地访问各个分组键。
- pd.merge()的suffixes参数: 使用suffixes=('_mean', '_sum')可以避免合并后出现同名列冲突,并清晰地标识出每个聚合结果的来源。
- np.arange(len(merged_df)): 这创建了一个等差数列,作为每个分组在Y轴上的基准位置。
- height1和位置偏移: height1定义了每个水平条形的高度。通过将第二个条形的位置设置为r1 + height1,可以使其紧邻第一个条形并排显示。如果使用plt.bar()绘制垂直条形图,则需要调整width和x轴位置。
- ax.set_yticks()和ax.set_yticklabels(): 对于水平条形图,Y轴代表分组类别。我们需要手动设置Y轴的刻度位置(r1 + height1 / 2将刻度标签置于两个条形之间)和刻度标签。通过遍历merged_df并格式化字符串,可以创建包含所有分组信息的清晰标签。
- plt.tight_layout(): 这个函数会自动调整子图参数,以给定的填充方式,使之适应图的布局,通常用于防止标签或标题重叠。
- 可读性: 选择合适的figsize、height(或width)、颜色和字体大小,可以显著提升图表的可读性。对于分组类别较多的情况,水平条形图(barh)通常比垂直条形图(bar)更适合显示长标签。
总结
通过上述步骤,我们成功地将两个基于相同分组但聚合方式不同的数据集(平均值和总和)合并,并在一个清晰的水平条形图中进行了并排可视化。这种方法不仅解决了直接绘制的难题,还提供了高度的灵活性和定制性,使您能够创建专业且易于理解的数据分析图表。掌握这种技术,对于进行多维度数据比较和报告展示非常有价值。
到这里,我们也就讲完了《Python多组groupby条形图合并教程》的内容了。个人认为,基础知识的学习和巩固,是为了更好的将其运用到项目中,欢迎关注golang学习网公众号,带你了解更多关于的知识点!
-
501 收藏
-
501 收藏
-
501 收藏
-
501 收藏
-
501 收藏
-
296 收藏
-
351 收藏
-
157 收藏
-
485 收藏
-
283 收藏
-
349 收藏
-
291 收藏
-
204 收藏
-
401 收藏
-
227 收藏
-
400 收藏
-
327 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 立即学习 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 立即学习 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 立即学习 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 立即学习 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 立即学习 485次学习