You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Seaborn在单图中绘制双图并合并图例的问题

合并双轴图表的图例(直方图+折线图)

我尝试在一张图中绘制两种图表:基于state和group统计频率的直方图,以及基于state统计target数值的折线图。希望将两个坐标轴(ax、ax2)的图例合并到同一个图例框中,但两种尝试方法均存在问题:

  • 方法1:可运行但生成两个独立图例框
h2, l2 = ax2.get_legend_handles_labels()
ax2.legend(h2, l2)
  • 方法2:仅显示target标签
h1, l1 = ax.get_legend_handles_labels()
h2, l2 = ax2.get_legend_handles_labels()
ax.legend(h1+h2, l1+l2, loc=2)

完整代码如下:

import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt

data = {
    'state': ['nj', 'nj', 'nj', 'ny', 'ny', 'ny'],
    'group': ['A', 'A', 'B', 'A', 'B', 'B'],
    'target': [20, 21, 19, 18, 15, 33]
}
df_test1 = pd.DataFrame(data)

fig, ax = plt.subplots(figsize=(10, 6))
sns.histplot(
    data=df_test1,
    x='state', 
    hue='group',
    hue_order=['A', 'B'], 
    multiple='dodge',
    ax=ax, 
    shrink=.5,
    )

ax2 = ax.twinx()
sns.lineplot(
    data=df_test1,
    x='state',
    y='target', 
    label='target',
    ax=ax2,
    )

h1, l1 = ax.get_legend_handles_labels()
h2, l2 = ax2.get_legend_handles_labels()
ax.legend(h1+h2, l1+l2, loc=2)

问题原因

方法2失效是因为seaborn.histplot使用hue参数时,默认不会将图例句柄直接存储在ax对象中,而是由Seaborn内部管理,导致ax.get_legend_handles_labels()返回空值。

解决代码

通过先让Seaborn生成直方图的图例,提取其句柄和标签后删除原始图例,再与折线图的图例元素合并:

import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt

data = {
    'state': ['nj', 'nj', 'nj', 'ny', 'ny', 'ny'],
    'group': ['A', 'A', 'B', 'A', 'B', 'B'],
    'target': [20, 21, 19, 18, 15, 33]
}
df_test1 = pd.DataFrame(data)

fig, ax = plt.subplots(figsize=(10, 6))
# 绘制直方图并获取图例元素
hist_plot = sns.histplot(
    data=df_test1,
    x='state', 
    hue='group',
    hue_order=['A', 'B'], 
    multiple='dodge',
    ax=ax, 
    shrink=.5,
)
h1, l1 = hist_plot.get_legend_handles_labels()
ax.get_legend().remove()  # 删除直方图的原始图例

# 绘制折线图并获取图例元素
ax2 = ax.twinx()
line_plot = sns.lineplot(
    data=df_test1,
    x='state',
    y='target', 
    label='target',
    ax=ax2,
)
h2, l2 = line_plot.get_legend_handles_labels()
ax2.get_legend().remove()  # 删除折线图的原始图例

# 合并所有图例元素到同一个图例框
ax.legend(h1 + h2, l1 + l2, loc=2)

plt.show()

效果说明

运行修改后的代码后,会生成一个包含直方图的A、B分类和折线图的target指标的统一图例框,解决了双轴图例分散或缺失的问题。


内容的提问来源于stack exchange,提问作者shsh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 01:07:48