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

Matplotlib子图绘制异常:第二个折线图无数据显示

问题解决:Matplotlib共享X轴时折线图无数据显示

问题背景

创建包含堆叠柱状图和折线图的子图布局,要求二者共享datetime类型的X轴,但折线图始终无数据渲染。

数据样例

日期EconomizerEconomizer_plus_MechNot_MechanicalOaTemp
2023-10-011.6806721.6806721.68067284.317815
2023-10-0217.1270725.5248621.65745976.263536
2023-10-0331.4814815.0925930.00000073.407407

原实现代码

import matplotlib.pyplot as plt
import os
import pandas as pd

PLOTS_DIR = 'path/to/plots'

def save_mode_plot_with_oat(combined_data, title, ylabel, filename):
    # 确保索引为datetime类型
    combined_data.index = pd.to_datetime(combined_data.index)

    # 创建2行子图,共享X轴
    fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(12, 12), sharex=True)

    # 第一个子图:堆叠柱状图
    combined_data.iloc[:, :-1].plot(kind='bar', stacked=True, ax=ax1, colormap='viridis')
    ax1.set_title(title)
    ax1.set_ylabel(ylabel)
    ax1.set_xlabel('')
    ax1.tick_params(axis='x', labelbottom=False)  # 隐藏第一个子图的X轴标签

    # 第二个子图:折线图(无数据显示)
    ax2.plot(combined_data.index, combined_data['OaTemp'], color='red', linestyle='-', marker='o')
    ax2.set_title('Average Outside Air Temperature Over Time')
    ax2.set_ylabel('Average Outside Air Temperature (°F)')
    ax2.set_xlabel('Date')
    ax2.tick_params(axis='x', rotation=90)
    ax2.grid(True)

    plt.tight_layout()
    plt.savefig(os.path.join(PLOTS_DIR, filename))
    plt.close()

# 调用示例
save_mode_plot_with_oat(month_df, 'Mode Percentages and OAT', 'Percentage (%)', 'mode_oat_plot.png')

问题原因

pandas的plot(kind='bar')会自动将datetime类型的索引转换为**整数位置(0,1,2...)**作为X轴坐标,开启sharex=True后,第二个子图的X轴会继承这个整数刻度体系。此时用datetime索引绘制折线图,数据的X坐标是实际日期值,和子图的整数刻度不匹配,导致折线图数据不在可见范围内。

解决方案

方法一:折线图用整数位置对齐(最简方案)

将折线图的X轴替换为数据行的整数位置,和柱状图的X轴刻度对齐,同时手动设置日期标签:

# 修改折线图绘制代码
ax2.plot(range(len(combined_data)), combined_data['OaTemp'], color='red', linestyle='-', marker='o')
# 设置正确的日期标签
ax2.set_xticks(range(len(combined_data)))
ax2.set_xticklabels(combined_data.index.strftime('%Y-%m-%d'))

修改后的完整代码

import matplotlib.pyplot as plt
import os
import pandas as pd

PLOTS_DIR = 'path/to/plots'

def save_mode_plot_with_oat(combined_data, title, ylabel, filename):
    combined_data.index = pd.to_datetime(combined_data.index)

    fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(12, 12), sharex=True)

    # 堆叠柱状图
    combined_data.iloc[:, :-1].plot(kind='bar', stacked=True, ax=ax1, colormap='viridis')
    ax1.set_title(title)
    ax1.set_ylabel(ylabel)
    ax1.set_xlabel('')
    ax1.tick_params(axis='x', labelbottom=False)

    # 折线图:用整数位置对齐X轴
    ax2.plot(range(len(combined_data)), combined_data['OaTemp'], color='red', linestyle='-', marker='o')
    ax2.set_title('Average Outside Air Temperature Over Time')
    ax2.set_ylabel('Average Outside Air Temperature (°F)')
    ax2.set_xlabel('Date')
    # 设置日期标签
    ax2.set_xticks(range(len(combined_data)))
    ax2.set_xticklabels(combined_data.index.strftime('%Y-%m-%d'))
    ax2.tick_params(axis='x', rotation=90)
    ax2.grid(True)

    plt.tight_layout()
    plt.savefig(os.path.join(PLOTS_DIR, filename))
    plt.close()

# 调用示例
save_mode_plot_with_oat(month_df, 'Mode Percentages and OAT', 'Percentage (%)', 'mode_oat_plot.png')

方法二:用Matplotlib原生bar绘制柱状图(保留datetime轴)

若希望X轴始终为datetime类型,可放弃pandas的plot方法,用Matplotlib原生bar函数手动绘制堆叠柱状图:

# 替换柱状图绘制部分
columns = combined_data.iloc[:, :-1].columns
bottom = 0
for col in columns:
    ax1.bar(combined_data.index, combined_data[col], bottom=bottom, label=col)
    bottom += combined_data[col]
ax1.legend()

这种方式下,折线图代码无需修改,X轴始终为datetime类型,共享后可正常对齐。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 12:34:58