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

Matplotlib未完整显示Pandas Dataframe数据及图例异常求助

问题描述
  • 数据存储:用Pandas Dataframe保存了3个月的6天滚动累计降雨量与Valentia天文台两个30年平均值(1961-1990、1991-2020)的差值数据,数据截止到2024年4月7日。
  • 绘图异常:
    1. 图表未显示全部数据:仅显示到3月,一年期数据甚至缺失最后5个月;尝试移除/保留x轴日期格式化、添加bbox_inches='tight'到plt.savefig均无效。
    2. 图例仅显示空框,无内容。
  • 怀疑方向:柱状图宽度或tight_layout导致,但未找到具体原因。

Dataframe首尾数据示例

TMSTAMP      diff_1961_1990    diff_1991_2020
0   2024-01-13     -100.000000     -100.000000
1   2024-01-14      -98.157863      -98.358824
2   2024-01-15      -24.472389      -32.711765
3   2024-01-16       11.756303       -0.435294
4   2024-01-17       22.809124        9.411765
..         ...             ...             ...
81  2024-04-03      218.307087      123.754613
82  2024-04-04      175.433071       93.616236
83  2024-04-05      170.236220       89.963100
84  2024-04-06      103.976378       43.385609
85  2024-04-07       93.582677       36.079336

绘图代码

def plot_yearly_6day_rolling_averages_diff_valentia(self):
    title = 'Plot 3 Month 6 Day Rolling Rainfall Average c/w Valentia Averages'
    fig = plt.figure(figsize=(800 / 96, 400 / 96), dpi=96)
    ax_rainfall = fig.add_subplot()
    plt.tight_layout()
    ax_rainfall.set_title(title, fontproperties=self.font_prop, fontweight='bold', size=10, color=self.colour_title)
    filename = '{}{}'.format(self.upload_folder, self.rainfall_6hrly_diff_valentia)
    x = self.df_rainfall_diff.index    
    y_1961_1990 = self.df_rainfall_diff['diff_1961_1990']
    y_1991_2020 = self.df_rainfall_diff['diff_1991_2020']
    ax_rainfall.set_ylabel('Rainfall Difference %', fontproperties=self.font_prop, size=8, color='fuchsia')
    major_fmt = md.DateFormatter('%m-%d')
    ax_rainfall.xaxis.set_major_formatter(major_fmt)
    plt.setp(ax_rainfall.xaxis.get_majorticklabels(), ha="center", rotation=45)
    ax_rainfall.xaxis.set_major_locator(MultipleLocator(7))
    ax_rainfall.yaxis.set_major_locator(MultipleLocator(20))
    ax_rainfall.yaxis.set_minor_locator(MultipleLocator(10))
    ax_rainfall.legend(loc="best")
    ax_rainfall.bar(x, y_1961_1990, width=0.05, color='fuchsia', label='Rainfall Difference 1961-1990 Valentia')
    ax_rainfall.bar(x + 0.2, y_1991_2020, width=0.05, color='blueviolet', label='Rainfall Difference 1991-2020 Valentia')
    plt.grid(which='both', linestyle='dotted', linewidth=0.3)
    plt.savefig(filename, format="png", transparent=True, dpi=96)
解决方案

1. 图例空框问题

你提前调用了ax_rainfall.legend(loc="best"),此时还未绘制任何带label的柱状图,导致图例无内容。必须把legend()调用放到绘制柱状图之后。

修改后代码片段:

# 先绘制柱状图
ax_rainfall.bar(x, y_1961_1990, width=0.05, color='fuchsia', label='Rainfall Difference 1961-1990 Valentia')
ax_rainfall.bar(x + 0.2, y_1991_2020, width=0.05, color='blueviolet', label='Rainfall Difference 1991-2020 Valentia')
# 再调用legend
ax_rainfall.legend(loc="best")

2. 数据显示不全问题

原因分析

  • 若TMSTAMP是普通列而非DatetimeIndex,x轴日期范围计算会出错;x + 0.2的数值偏移对日期索引不适用,会挤压后期数据的显示空间。
  • plt.tight_layout()调用过早,布局计算未包含所有绘图元素,导致范围截断。
  • MultipleLocator(7)的x轴定位器可能未覆盖到最后一组数据的刻度范围。

修复步骤

  1. 将日期列转为DatetimeIndex:
    self.df_rainfall_diff['TMSTAMP'] = pd.to_datetime(self.df_rainfall_diff['TMSTAMP'])
    self.df_rainfall_diff.set_index('TMSTAMP', inplace=True)
    
  2. 调整柱状图的日期偏移方式:
    用时间差代替数值偏移,适配日期索引:
    ax_rainfall.bar(x, y_1961_1990, width=0.05, color='fuchsia', label='Rainfall Difference 1961-1990 Valentia')
    ax_rainfall.bar(x + pd.Timedelta(days=0.2), y_1991_2020, width=0.05, color='blueviolet', label='Rainfall Difference 1991-2020 Valentia')
    
  3. 调整布局与坐标轴范围:
    • 把plt.tight_layout()移到所有绘图元素之后、保存图片之前。
    • 手动设置x轴范围,确保包含全部数据:
      ax_rainfall.set_xlim(self.df_rainfall_diff.index.min(), self.df_rainfall_diff.index.max() + pd.Timedelta(days=0.5))
      
  4. 优化保存参数:
    添加bbox_inches='tight'防止内容被裁剪:
    plt.savefig(filename, format="png", transparent=True, dpi=96, bbox_inches='tight')
    

完整修复后的代码

def plot_yearly_6day_rolling_averages_diff_valentia(self):
    # 确保TMSTAMP是DatetimeIndex
    self.df_rainfall_diff['TMSTAMP'] = pd.to_datetime(self.df_rainfall_diff['TMSTAMP'])
    self.df_rainfall_diff.set_index('TMSTAMP', inplace=True)
    
    title = 'Plot 3 Month 6 Day Rolling Rainfall Average c/w Valentia Averages'
    fig = plt.figure(figsize=(800 / 96, 400 / 96), dpi=96)
    ax_rainfall = fig.add_subplot()
    
    ax_rainfall.set_title(title, fontproperties=self.font_prop, fontweight='bold', size=10, color=self.colour_title)
    filename = '{}{}'.format(self.upload_folder, self.rainfall_6hrly_diff_valentia)
    
    x = self.df_rainfall_diff.index    
    y_1961_1990 = self.df_rainfall_diff['diff_1961_1990']
    y_1991_2020 = self.df_rainfall_diff['diff_1991_2020']
    
    ax_rainfall.set_ylabel('Rainfall Difference %', fontproperties=self.font_prop, size=8, color='fuchsia')
    major_fmt = md.DateFormatter('%m-%d')
    ax_rainfall.xaxis.set_major_formatter(major_fmt)
    plt.setp(ax_rainfall.xaxis.get_majorticklabels(), ha="center", rotation=45)
    
    ax_rainfall.xaxis.set_major_locator(MultipleLocator(7))
    ax_rainfall.yaxis.set_major_locator(MultipleLocator(20))
    ax_rainfall.yaxis.set_minor_locator(MultipleLocator(10))
    
    # 先绘制柱状图
    ax_rainfall.bar(x, y_1961_1990, width=0.05, color='fuchsia', label='Rainfall Difference 1961-1990 Valentia')
    ax_rainfall.bar(x + pd.Timedelta(days=0.2), y_1991_2020, width=0.05, color='blueviolet', label='Rainfall Difference 1991-2020 Valentia')
    
    # 设置x轴范围确保包含所有数据
    ax_rainfall.set_xlim(x.min(), x.max() + pd.Timedelta(days=0.5))
    
    ax_rainfall.legend(loc="best")
    plt.grid(which='both', linestyle='dotted', linewidth=0.3)
    
    # 最后调用tight_layout和保存
    plt.tight_layout()
    plt.savefig(filename, format="png", transparent=True, dpi=96, bbox_inches='tight')

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 00:08:13