Matplotlib未完整显示Pandas Dataframe数据及图例异常求助
问题描述
- 数据存储:用Pandas Dataframe保存了3个月的6天滚动累计降雨量与Valentia天文台两个30年平均值(1961-1990、1991-2020)的差值数据,数据截止到2024年4月7日。
- 绘图异常:
- 图表未显示全部数据:仅显示到3月,一年期数据甚至缺失最后5个月;尝试移除/保留x轴日期格式化、添加
bbox_inches='tight'到plt.savefig均无效。 - 图例仅显示空框,无内容。
- 图表未显示全部数据:仅显示到3月,一年期数据甚至缺失最后5个月;尝试移除/保留x轴日期格式化、添加
- 怀疑方向:柱状图宽度或
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轴定位器可能未覆盖到最后一组数据的刻度范围。
修复步骤
- 将日期列转为DatetimeIndex:
self.df_rainfall_diff['TMSTAMP'] = pd.to_datetime(self.df_rainfall_diff['TMSTAMP']) self.df_rainfall_diff.set_index('TMSTAMP', inplace=True) - 调整柱状图的日期偏移方式:
用时间差代替数值偏移,适配日期索引: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') - 调整布局与坐标轴范围:
- 把
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))
- 把
- 优化保存参数:
添加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
相关产品推荐
相关产品推荐

