You need to enable JavaScript to run this app. matplotlib循环分月绘制气象时间序列首月数据不显示及子图保存异常
优惠活动
大模型
产品
解决方案
定价
更多

matplotlib循环分月绘制气象时间序列首月数据不显示及子图保存异常

核心问题定位与修复

你的判断方向完全正确,所有问题根源都是matplotlib figure对象的引用被循环逻辑反复覆盖,不存在底层机制的理解门槛问题,具体错误和修复如下:

错误1:1月子图无法渲染的根因

你的原始代码在循环内的执行顺序完全打乱了figure的生命周期:

  • 当循环进入第一次迭代(处理1月数据)时,你已经把1月的气象数据画到了初始的空figure上
  • 但循环末尾你写了fig = plt.figure(figsize=(20, 5)),这行代码会生成一个全新的空白figure,直接把之前存放1月绘图内容的figure的引用覆盖掉
  • 后续从2月到12月的所有绘图,都画在这个被反复覆盖的新figure上,而存放1月内容的figure因为没有有效引用,直接被matplotlib的内存管理机制回收,最终渲染时自然看不到1月的子图。

你第二次调整的代码这个问题更严重:循环外刚生成了带6行2列共12个空axes的正确figure,结果循环第一行就写fig = plt.figure(figsize=(200, 50)),每处理一个月就重新生成一个空白figure,完全把之前初始化的axes所属的figure引用丢弃了。

错误2:无法正确导出整幅figure的根因

导出失败的原因同样是引用覆盖:

  • 你循环结束后,又额外执行了fig = plt.figure()生成了一个完全空白的新figure
  • 此时你调用fig.savefig(),保存的就是这个完全没有任何绘图内容的空白对象,之前画在原6行2列布局上的12个月份子图,因为fig引用被反复覆盖,根本不在当前保存的对象上。

具体修复规则

  • 所有figure、axes对象的初始化必须放在循环外部,整个绘图流程中绝对不能重新给fig变量赋值、不能随意新建figure
  • 自定义Meteogram类的方法不要自行创建子图,必须使用外部传入的已经初始化好的axes对象
  • 类内部不要依赖循环内的全局变量(比如starttime、endtime),所有动态状态要通过参数传入,避免跨循环的变量值串扰
  • savefig操作必须在循环结束后、直接引用最开始初始化的那个figure对象,绝不能在savefig之前重新创建新的figure

修正后的核心可运行代码

from calendar import monthrange
import datetime as dt
import matplotlib as mpl
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np

# 循环外统一初始化figure和所有子图,整个流程绝不覆盖fig引用
fig, axes = plt.subplots(nrows=6, ncols=2, figsize=(20, 60))
probe_id = 'SOCA'
year = 2019

class Meteogram:
    def __init__(self, dates, start_time, end_time, probeid):
        # 去掉对全局变量的依赖,所有状态通过参数传入
        self.start = start_time
        self.end = end_time
        self.dates = mpl.dates.date2num(dates)
        self.probeid = probeid

    def plot_winds(self, ws, wd, wsmax, ax, plot_range=None):
        # 直接使用传入的ax,不自行创建子图
        self.ax1 = ax
        ln1 = self.ax1.plot(self.dates, ws, label='Wind Speed')
        self.ax1.fill_between(self.dates, ws, 0)
        self.ax1.set_xlim(self.start, self.end)
        if not plot_range:
            plot_range = [0, 30, 5]
        self.ax1.set_ylabel(f'Wind Speed (knots)\n{self.start.strftime("%Y-%m")}')
        self.ax1.set_ylim(plot_range[0], plot_range[1], plot_range[2])
        self.ax1.grid(b=True, which='major', axis='y', color='k', linestyle='-', linewidth=0.5)
        ln2 = self.ax1.plot(self.dates, wsmax, '.r', label='Gust')

        ax7 = self.ax1.twinx()
        ln3 = ax7.plot(self.dates, wd, '.k', linewidth=0.1, label='Wind Direction')
        ax7.set_ylabel('Wind\nDirection\n(degrees)', multialignment='center')
        ax7.set_ylim(0, 360)
        ax7.set_yticks(np.arange(45, 405, 90), ['NE', 'SE', 'SW', 'NW'])
        
        lines = ln1 + ln2 + ln3
        labs = [line.get_label() for line in lines]
        ax7.xaxis.set_major_formatter(mpl.dates.DateFormatter('%m/%d'))
        ax7.legend(lines, labs, loc='center', bbox_to_anchor=(.9, -0.25), ncol=3, prop={'size': 10})

# 循环内仅做数据处理、绘图,不创建新figure
for months in range(1, 13):
    # 计算当月的时间范围
    _, month_day_count = monthrange(year, months)
    endtime = dt.datetime(year, months, month_day_count, 0, 0)
    starttime = dt.datetime(year, months, 1, 0, 0)

    # 过滤当月数据
    df_new = df[(df['ICAO'] == probe_id) & (df['month'] == months)].copy()
    # 数据类型转换
    for col in ['wind_speed', 'wind_dir', 'wind_gust', 'temp', 'dewpt', 'press']:
        df_new[col] = pd.to_numeric(df_new[col], errors='coerce')
    df_new['wind_gust'] = df_new['wind_gust'].fillna(0)

    # 获取对应位置的ax(6行2列布局,顺序为1-2月第一行,3-4月第二行...)
    row_idx = (months - 1) // 2
    col_idx = (months - 1) % 2
    target_ax = axes[row_idx, col_idx]

    # 实例化meteogram并绘图
    meteogram = Meteogram(
        dates=df_new['datetime'],
        start_time=starttime,
        end_time=endtime,
        probeid=probe_id
    )
    meteogram.plot_winds(
        ws=df_new['wind_speed'],
        wd=df_new['wind_dir'],
        wsmax=df_new['wind_gust'],
        ax=target_ax
    )

# 循环结束后统一调整布局、保存图片,绝不新建figure
fig.tight_layout()
fig.subplots_adjust(hspace=0.5, wspace=0.3)
fig.savefig('monthly_meteogram_2019.png', dpi=150, bbox_inches='tight')

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.31 18:36:04