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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 22:09:53