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

Seaborn多子图双Y轴配置异常问题:如何正确设置副轴标签与统一刻度范围

Seaborn多子图双Y轴配置问题:避免重复创建副轴

提问内容

您好,StackOverflow社区,我是一名新手,目前遇到了Seaborn多子图双Y轴的配置问题,以下是我的代码:

fig, axs = plt.subplots(2, 2, figsize=(20,20), dpi=(100))
axs[0,0].set_title('2017, Zeitreihe, Zähler: ' + Zaehler)
sns.lineplot(data= data_heatmap_2017, x='date_time', y= 'Leistung:', linewidth=0.1, ax=axs[0,0])
sns.lineplot(data= data_heatmap_2017, x='date_time', y= 'tre200h0_2017', linewidth=0.1, color='orange', ax=axs[0,0].twinx())
axs[0,0].xaxis.set_major_locator(ticker.MultipleLocator(1000))
axs[0,0].tick_params(axis='x', labelrotation=90)
axs[0,0].set_ylabel('Leistung [kW]')
axs[0,0].set_ylim([min_Power, max_Power])
axs[0,0].twinx().set_ylabel('Aussentemperatur [°C]')
axs[0,0].twinx().set_ylim([-15, 35])
axs[0,1].set_title('2018, Zeitreihe, Zähler: ' + Zaehler)
sns.lineplot(data= data_heatmap_2018, x='date_time', y= 'Leistung:', linewidth=0.1, ax=axs[0,1])
sns.lineplot(data= data_heatmap_2018, x='date_time', y= 'tre200h0_2018', linewidth=0.1, color='orange', ax=axs[0,1].twinx())
axs[0,1].xaxis.set_major_locator(ticker.MultipleLocator(1000))
axs[0,1].tick_params(axis='x', labelrotation=90)
axs[0,1].set_ylabel('Leistung [kW]')
axs[0,1].set_ylim([min_Power, max_Power])
axs[0,1].twinx().set_ylabel('Aussentemperatur [°C]')
axs[0,1].twinx().set_ylim([-15, 35])
# a lot more plots will come here

如图片所示,双Y轴的配置出现了问题:每个子图的副Y轴应标注为“Aussentemperatur”,且为了便于对比,副Y轴的刻度范围需统一设置为-15到35℃。我尝试使用.twinx().set_ylabel('Aussentemperatur [°C]')设置标签,用.twinx().set_ylim([-15, 35])设置刻度范围,但每次调用twinx()都会创建新的副轴,导致轴重叠,无法正常显示清晰的-15到35℃的刻度轴。请问如何解决该问题,实现正确的副轴配置?


解决方案

问题根源

你每次调用ax.twinx()都会生成一个全新的右侧Y轴,多次调用就会叠加多个副轴,这就是为什么你看到轴标签和刻度混乱的原因。正确的做法是只创建一次副轴,然后复用这个对象来设置标签、刻度和绘图。

修正后的代码示例

我们可以把每个子图的副轴对象先保存下来,之后所有对副轴的操作都基于这个对象,而不是反复调用twinx():

import matplotlib.pyplot as plt
import seaborn as sns
import matplotlib.ticker as ticker

# 假设你已经定义了这些变量:Zaehler, min_Power, max_Power, data_heatmap_2017, data_heatmap_2018

fig, axs = plt.subplots(2, 2, figsize=(20,20), dpi=100)

# 处理第一个子图 (0,0)
ax_main = axs[0,0]
ax_main.set_title('2017, Zeitreihe, Zähler: ' + Zaehler)
# 主Y轴绘图
sns.lineplot(data=data_heatmap_2017, x='date_time', y='Leistung:', linewidth=0.1, ax=ax_main)
# 创建并保存副轴对象
ax_twin = ax_main.twinx()
# 副Y轴绘图
sns.lineplot(data=data_heatmap_2017, x='date_time', y='tre200h0_2017', linewidth=0.1, color='orange', ax=ax_twin)

# 配置主轴
ax_main.xaxis.set_major_locator(ticker.MultipleLocator(1000))
ax_main.tick_params(axis='x', labelrotation=90)
ax_main.set_ylabel('Leistung [kW]')
ax_main.set_ylim([min_Power, max_Power])

# 配置副轴(复用之前创建的ax_twin)
ax_twin.set_ylabel('Aussentemperatur [°C]')
ax_twin.set_ylim([-15, 35])

# 处理第二个子图 (0,1)
ax_main = axs[0,1]
ax_main.set_title('2018, Zeitreihe, Zähler: ' + Zaehler)
sns.lineplot(data=data_heatmap_2018, x='date_time', y='Leistung:', linewidth=0.1, ax=ax_main)
ax_twin = ax_main.twinx()
sns.lineplot(data=data_heatmap_2018, x='date_time', y='tre200h0_2018', linewidth=0.1, color='orange', ax=ax_twin)

ax_main.xaxis.set_major_locator(ticker.MultipleLocator(1000))
ax_main.tick_params(axis='x', labelrotation=90)
ax_main.set_ylabel('Leistung [kW]')
ax_main.set_ylim([min_Power, max_Power])

ax_twin.set_ylabel('Aussentemperatur [°C]')
ax_twin.set_ylim([-15, 35])

# 后续子图都可以按照这个模式来,先创建并保存副轴对象,再复用它配置参数

额外优化建议

如果后续有大量子图需要处理,你可以把重复的逻辑封装成一个函数,减少代码冗余,让代码更简洁易维护:

def plot_dual_axis(ax_main, data, title, y_main_col, y_twin_col, y_main_label, y_twin_label, y_main_lim, y_twin_lim):
    ax_main.set_title(title)
    sns.lineplot(data=data, x='date_time', y=y_main_col, linewidth=0.1, ax=ax_main)
    ax_twin = ax_main.twinx()
    sns.lineplot(data=data, x='date_time', y=y_twin_col, linewidth=0.1, color='orange', ax=ax_twin)
    
    ax_main.xaxis.set_major_locator(ticker.MultipleLocator(1000))
    ax_main.tick_params(axis='x', labelrotation=90)
    ax_main.set_ylabel(y_main_label)
    ax_main.set_ylim(y_main_lim)
    
    ax_twin.set_ylabel(y_twin_label)
    ax_twin.set_ylim(y_twin_lim)
    return ax_twin

# 调用示例
plot_dual_axis(
    axs[0,0], 
    data_heatmap_2017, 
    '2017, Zeitreihe, Zähler: ' + Zaehler,
    'Leistung:',
    'tre200h0_2017',
    'Leistung [kW]',
    'Aussentemperatur [°C]',
    [min_Power, max_Power],
    [-15, 35]
)

plot_dual_axis(
    axs[0,1], 
    data_heatmap_2018, 
    '2018, Zeitreihe, Zähler: ' + Zaehler,
    'Leistung:',
    'tre200h0_2018',
    'Leistung [kW]',
    'Aussentemperatur [°C]',
    [min_Power, max_Power],
    [-15, 35]
)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.28 17:39:10