如何实现每个y轴支持多列的多坐标轴pandas DataFrame绘图功能
多Y轴共享绘图函数实现方案
直接上可运行的完整实现代码:
import pandas as pd import matplotlib.pyplot as plt from typing import List def plot_df(df: pd.DataFrame, x_column: str, columns: List[List[str]]): """Plot DataFrame using `x_column` on the x-axis and `len(columns)` different y-axes where the axis numbered `i` is calibrated to render the columns in `columns[i]`. 核心要求: 1. 全图仅保留1个图例 2. 每个列对应的绘图线条使用不同的颜色 坐标轴可匹配对应分组下任意一个线条的颜色,并关联对应分组标签(比如价格轴、收益率轴、增长率轴) """ # 预生成足够多的唯一颜色,默认使用tab20调色板最多支持20个不同列,可按需替换其他调色板 all_columns = [col for group in columns for col in group] colors = plt.cm.tab20.colors[:len(all_columns)] color_map = dict(zip(all_columns, colors)) fig, host_ax = plt.subplots(figsize=(10,6)) axes = [host_ax] all_handles = [] # 额外的y轴向右偏移,避免重叠 offset = 60 for i, group in enumerate(columns): # 第一个组用host轴,其余生成twinx轴 if i > 0: ax = host_ax.twinx() # 超过第二个的轴需要向右移动位置 if i > 1: ax.spines.right.set_position(("axes", 1 + (i-1)*offset/100)) axes.append(ax) else: ax = host_ax # 绘制当前分组下的所有列,每个列用唯一颜色 for col in group: line, = ax.plot(df[x_column], df[col], color=color_map[col], label=col) all_handles.append(line) # 坐标轴用分组第一个列的颜色匹配,设置轴标签 group_first_col = group[0] ax.set_ylabel(f"{group_first_col}组轴", color=color_map[group_first_col]) ax.tick_params(axis='y', colors=color_map[group_first_col]) # 全局仅保留一个图例 host_ax.legend(handles=all_handles, loc='upper left') # 调整布局避免轴标签被截断 fig.tight_layout() plt.show()
核心逻辑说明
- 提前为所有需要绘制的列分配全局唯一的颜色,从根源避免同色冲突
- 同一分组的列全部绘制在同一个twinx生成的坐标轴上,每个坐标轴独立校准刻度范围,互不影响
- 所有线条的图例句柄统一收集后,由主坐标轴生成唯一的全局图例,避免多图例重复
- 坐标轴颜色默认匹配分组第一个列的线条颜色,可按需修改为分组内任意列的颜色
测试用例
你给出的示例可直接运行测试:
# 构造测试数据 import numpy as np dates = pd.date_range(start='2023-01-01', periods=100) df = pd.DataFrame({ 'time': dates, 'price1': np.cumsum(np.random.randn(100)) + 100, 'price2': np.cumsum(np.random.randn(100)) + 200, 'returns': np.random.randn(100)*0.05, 'growth': np.cumsum(np.random.randn(100)) + 10 }) # 调用函数 plot_df(df, 'time', [['price1', 'price2'], ['returns'], ['growth']])
运行后会生成符合要求的3个Y轴图表,price1和price2共享第一个Y轴,returns和growth分别使用独立的第二、第三个Y轴,所有线条颜色唯一,全局只有一个图例。
内容的提问来源于stack exchange,提问作者Peteris
相关产品推荐
相关产品推荐

