如何基于Pandas循环生成Matplotlib三Y轴组合图表?
解决循环生成三Y轴图表重复问题的方案
核心问题分析
循环生成图表时内容重复,通常是因为没有在每次循环中创建全新的图表实例,或者数据过滤逻辑有误,导致每次循环复用了同一个图表对象/数据子集。
实现步骤与代码示例
假设你的df0包含Code、Date、Value1(柱状图)、Value2(折线1)、Value3(折线2)这些字段,以下是完整的可运行代码:
- 模拟测试数据(可替换为你自己的
df0)
import pandas as pd import matplotlib.pyplot as plt import numpy as np # 构造示例数据集 dates = pd.date_range('2023-01-01', periods=6) codes = ['A', 'B'] df0 = pd.DataFrame({ 'Code': np.repeat(codes, 6), 'Date': dates.tolist() * 2, 'Value1': np.random.randint(10, 50, size=12), 'Value2': np.random.randint(100, 500, size=12), 'Value3': np.random.randint(1000, 5000, size=12) })
- 提取唯一Code并循环生成三Y轴图表
# 获取所有唯一的Code值 unique_codes = df0['Code'].unique() for code in unique_codes: # 1. 过滤当前Code对应的数据集 df_sub = df0[df0['Code'] == code].reset_index(drop=True) # 2. 每次循环创建全新的图表和主坐标轴(核心:避免复用旧图表对象) fig, ax1 = plt.subplots(figsize=(10, 6)) # 3. 第一个Y轴:绘制柱状图(对应Value1) ax1.bar(df_sub['Date'], df_sub['Value1'], color='tab:blue', alpha=0.6) ax1.set_xlabel('日期') ax1.set_ylabel('Value1', color='tab:blue') ax1.tick_params(axis='y', labelcolor='tab:blue') ax1.tick_params(axis='x', rotation=45) # 4. 第二个Y轴:绘制折线图(对应Value2) ax2 = ax1.twinx() ax2.plot(df_sub['Date'], df_sub['Value2'], color='tab:orange', marker='o', linewidth=2) ax2.set_ylabel('Value2', color='tab:orange') ax2.tick_params(axis='y', labelcolor='tab:orange') # 5. 第三个Y轴:绘制折线图(对应Value3) ax3 = ax1.twinx() # 调整第三个Y轴的位置,避免和第二个Y轴重叠 ax3.spines['right'].set_position(('axes', 1.2)) ax3.plot(df_sub['Date'], df_sub['Value3'], color='tab:green', marker='s', linewidth=2) ax3.set_ylabel('Value3', color='tab:green') ax3.tick_params(axis='y', labelcolor='tab:green') # 6. 添加标题和合并图例 fig.suptitle(f'Code {code} 三Y轴组合图表', fontsize=12) # 手动创建图例,合并多轴元素 from matplotlib.patches import Patch from matplotlib.lines import Line2D legend_elements = [ Patch(facecolor='tab:blue', alpha=0.6, label='Value1'), Line2D([0], [0], color='tab:orange', marker='o', label='Value2'), Line2D([0], [0], color='tab:green', marker='s', label='Value3') ] fig.legend(handles=legend_elements, loc='upper right', bbox_to_anchor=(1.15, 0.9)) # 调整布局,防止标签被截断 fig.tight_layout() plt.show()
关键注意事项
- 每次循环新建图表:
fig, ax1 = plt.subplots(...)必须放在循环内部,确保每个Code对应独立的图表实例。 - 数据过滤精准:
df_sub = df0[df0['Code'] == code]要严格筛选当前Code的数据,避免跨Code数据混淆。 - 多Y轴位置调整:通过
ax3.spines['right'].set_position(('axes', 1.2))调整第三个Y轴的位置,防止和第二个Y轴重叠。 - 图例手动合并:多轴图表无法自动合并图例,需要手动创建图例元素并添加到figure上。
内容的提问来源于stack exchange,提问作者Flint
相关产品推荐
相关产品推荐

