求助:基于Pandas分组后的DataFrame绘制多幅图表
按名称分别绘制分组统计图表的实现方法
首先,你的原始数据和分组操作如下:
原始DataFrame代码
import pandas as pd name=['name1', 'name1', 'name1', 'name1', 'name2', 'name2', 'name3'] date=['2023/01/01', '2023/02/01', '2023/02/01', '2023/03/01', '2023/01/01', '2023/02/01', '2023/01/01', ] quantity=[5, 3, 15, 10, 5, 15, 10] site=['site1', 'site1', 'site2', 'site3', 'site1', 'site2', 'site3', ] df= pd.DataFrame({'name':name, 'date': date, 'quantity': quantity, 'site': site})
分组统计操作
grouped_df = df.groupby(by=['name', 'date']).agg({'quantity':['sum'], 'site': ['count']})
分组后的结果存在多级列,需要先处理扁平化,再按name分别绘图。以下是完整实现方案:
步骤1:预处理分组数据
将多级列转为单级列,并重置索引让name和date成为普通列:
# 扁平化多级列名 grouped_df.columns = ['quantity_sum', 'site_count'] # 重置索引,将name和date从索引转为列 grouped_df = grouped_df.reset_index()
步骤2:按name循环绘制图表
使用matplotlib实现双Y轴图表(适配两个指标的量级差异),代码如下:
import matplotlib.pyplot as plt # 获取所有唯一的名称 unique_names = grouped_df['name'].unique() # 遍历每个名称生成独立图表 for name in unique_names: # 筛选当前名称的数据子集 subset = grouped_df[grouped_df['name'] == name] # 创建画布 plt.figure(figsize=(8, 5)) # 第一个Y轴:绘制总数量(柱状图) ax1 = plt.gca() ax1.bar(subset['date'], subset['quantity_sum'], width=0.4, color='skyblue', label='总数量') ax1.set_xlabel('日期') ax1.set_ylabel('总数量') ax1.tick_params(axis='y', labelcolor='skyblue') # 第二个Y轴:绘制站点数量(折线图) ax2 = ax1.twinx() ax2.plot(subset['date'], subset['site_count'], marker='o', color='orange', label='站点数量') ax2.set_ylabel('站点数量') ax2.tick_params(axis='y', labelcolor='orange') # 设置标题和图例 plt.title(f'{name} 统计数据') lines1, labels1 = ax1.get_legend_handles_labels() lines2, labels2 = ax2.get_legend_handles_labels() ax1.legend(lines1 + lines2, labels1 + labels2, loc='upper left') # 调整布局并显示图表 plt.tight_layout() plt.show()
可选:单Y轴图表实现
如果不需要区分量级,也可以用单Y轴同时展示两个指标:
for name in unique_names: subset = grouped_df[grouped_df['name'] == name] plt.figure(figsize=(8, 5)) # 用柱状图同时展示两个指标 subset.plot(x='date', y=['quantity_sum', 'site_count'], kind='bar', ax=plt.gca()) plt.title(f'{name} 统计数据') plt.xlabel('日期') plt.ylabel('数值') plt.legend(['总数量', '站点数量']) plt.tight_layout() plt.show()
内容的提问来源于stack exchange,提问作者goanes
相关产品推荐
相关产品推荐

