Python脚本与Jupyter Notebook绘图异常求助:重叠与图例缺失
PyCharm绘图问题修复方案
问题描述
在PyCharm中运行Python绘图脚本时出现两个问题:图像元素重叠,图例不显示,但相同代码在Jupyter Notebook中运行正常。需求是批量运行脚本后自动保存大量图像,原代码如下:
t_train = np.load('t_train.npy') x_dot_test_computed = np.load('x_dot_test_computed.npy') x_dot_test_predicted = np.load('x_dot_test_predicted.npy') num_columns = x_dot_test_computed.shape[1] # fig, axs = plt.subplots(num_columns, 1, figsize=(9,10), sharex=True) fig, axs = plt.subplots(num_columns, 1, sharex=True) # If only one column, axs may not be an array, handle this case: if num_columns == 1: axs = [axs] # Make it iterable for i in range(num_columns): # Plot each column of data axs[i].plot(t_train, x_dot_test_computed[:, i], "b-", label="Computed" if i == 0 else "_nolegend_") axs[i].plot(t_train, x_dot_test_predicted[:, i], "r-", label="Predicted" if i == 0 else "_nolegend_") axs[i].set_ylabel(r"$\dot x_{}$".format(i)) # Set common x-label axs[-1].set_xlabel("Time (t)") # Adding a single legend for the entire figure, outside the last subplot fig.legend(loc="lower center", bbox_to_anchor=(0.5, -0.05), fancybox=True, shadow=True, ncol=2) # Adjust layout to prevent overlap and make sure everything fits well plt.tight_layout() # Adjust the bottom margin to make space for the legend plt.subplots_adjust(bottom=0.2) plot_dir = 'SavedPlots' if not os.path.exists(plot_dir): os.makedirs(plot_dir) # Save the figure in PDF and PNG format with high resolution plt.savefig(f'{plot_dir}/plot_high_res1.pdf', format='pdf', dpi=300) plt.savefig(f'{plot_dir}/plot_high_res1.png', format='png', dpi=300) # Show the plot plt.show()
问题原因与修复方案
1. 图像重叠问题
- 原代码注释了
figsize设置,默认画布尺寸过小,导致子图、标签拥挤重叠。需根据子图数量动态设置合适的画布高度。 plt.tight_layout()和plt.subplots_adjust()调用顺序错误:tight_layout()会重置布局参数,应放在布局调整之后,或直接用其rect参数预留图例空间。
2. 图例不显示问题
- PyCharm非交互式环境下,
fig.legend()需明确获取有效图例句柄,仅靠标签判断可能失效。需手动提取第一次绘图的线条句柄来创建图例。
修正后的完整代码
import numpy as np import matplotlib.pyplot as plt import os t_train = np.load('t_train.npy') x_dot_test_computed = np.load('x_dot_test_computed.npy') x_dot_test_predicted = np.load('x_dot_test_predicted.npy') num_columns = x_dot_test_computed.shape[1] # 动态设置画布大小,按子图数量分配高度(每个子图2.5英寸) fig, axs = plt.subplots(num_columns, 1, figsize=(9, num_columns * 2.5), sharex=True) # 处理单列子图的非数组情况 if num_columns == 1: axs = [axs] # 存储图例句柄与标签,确保图例能正确识别 handles = [] labels = [] for i in range(num_columns): # 绘制计算值和预测值,保存线条对象 line1, = axs[i].plot(t_train, x_dot_test_computed[:, i], "b-") line2, = axs[i].plot(t_train, x_dot_test_predicted[:, i], "r-") axs[i].set_ylabel(r"$\dot x_{}$".format(i)) # 仅在第一次循环时记录图例信息 if i == 0: handles = [line1, line2] labels = ["Computed", "Predicted"] # 设置公共X轴标签 axs[-1].set_xlabel("Time (t)") # 使用手动提取的句柄创建图例,确保显示正常 fig.legend(handles=handles, labels=labels, loc="lower center", bbox_to_anchor=(0.5, -0.08), fancybox=True, shadow=True, ncol=2) # 用tight_layout的rect参数预留底部空间,避免布局冲突 plt.tight_layout(rect=[0, 0.1, 1, 1]) # 创建保存目录 plot_dir = 'SavedPlots' if not os.path.exists(plot_dir): os.makedirs(plot_dir) # 保存图像时添加bbox_inches='tight',确保图例完整保存 plt.savefig(f'{plot_dir}/plot_high_res1.pdf', format='pdf', dpi=300, bbox_inches='tight') plt.savefig(f'{plot_dir}/plot_high_res1.png', format='png', dpi=300, bbox_inches='tight') plt.show()
关键修改说明
- 动态设置
figsize:根据子图数量计算画布高度,从根源避免内容拥挤。 - 手动提取图例句柄:解决PyCharm环境下自动识别图例失效的问题。
- 优化布局逻辑:用
tight_layout(rect)替代subplots_adjust,避免布局参数冲突。 - 保存时添加
bbox_inches='tight':确保图例和所有元素都被完整保存到输出文件中。
内容的提问来源于stack exchange,提问作者JuanMuñoz
相关产品推荐
相关产品推荐

