Matplotlib非常缓慢。这正常吗?

16

我正在使用matplotlib创建一些pdf图表,其中包含400个子图。每个子图只有5个数据点。在一台性能良好的计算机上保存5张pdf图片需要420秒。有没有什么方法可以优化代码,或者这对于matplotlib来说是很正常的?

用于绘图的部分代码:

plot_cnt = 1
for k in np.arange(K_min, K_max + 1):
    for l in np.arange(L_min, L_max + 1):
        ax = plt.subplot(grid[0], grid[1], plot_cnt)
        plot_cnt += 1
        plt.setp(ax, 'frame_on', False)
        ax.set_ylim([-0.1, 1.1])
        ax.set_xlabel('K={},L={}'.format(k, l), size=3)
        ax.set_xlim([-0.1, 4.1])
        ax.set_xticks([])
        ax.set_yticks([])
        ax.grid('off')
        ax.plot(np.arange(5), (data['S1']['Azimuth'][:, k - 1, l + offset_l] + \
                data['S1']['Delta Speed'][:, k - 1, l + offset_l] + \
                data['S1']['Speed'][:, k - 1, l + offset_l]) / 3,
                'r-o', ms=1, mew=0, mfc='r')
        ax.plot(np.arange(5), data['S2'][case][:, k - 1, l + offset_l],
                'b-o', ms=1, mew=0, mfc='b')
plt.savefig(os.path.join(os.getcwd(), 'plot-average.pdf'))
plt.clf()
print 'Final plot created.'

最终图片: 在此输入图片描述


3
对我来说,400个子图似乎很多。即使您没有很多数据,matplotlib也可能无法优化显示此类网格。 - Simon Bergot
1
@Simon,是否可以使用单个大subplot绘制图形?然后每五个应该连接在一起。有什么想法吗? - rowman
我没有合适的环境来运行测试,但你可以尝试一些方法。第一步是在你的代码上运行分析器(更多信息请参见这里)。通过这个,你可以找到时间花费的地方。你可以尝试两件事情:在每个步骤中找到一些资源来释放,或者使用multiprocessing在几个进程中创建图形。如果我有时间,我会尝试这个,但现阶段我不能保证任何东西。 - Simon Bergot
1
@rowman 我实现了您使用一个大“axes”的想法。 - tacaswell
1个回答

24

在@rowman所说的基础上,您可以在一个坐标轴中完成所有操作(关闭所有刻度等)。类似于:

构建于@rowman所说的基础之上,您可以在一个坐标轴中完成所有操作(关闭所有刻度等)。类似于:

K_max = 20
K_min = 0
L_max = 20
L_min = 0
ax = plt.subplot(111)
x_offset = 7 # tune these
y_offset = 7 # tune these
plt.setp(ax, 'frame_on', False)
ax.set_ylim([0, (K_max-K_min +1)*y_offset ])
ax.set_xlim([0, (L_max - L_min+1)*x_offset])
ax.set_xticks([])
ax.set_yticks([])
ax.grid('off')



for k in np.arange(K_min, K_max + 1):
    for l in np.arange(L_min, L_max + 1):
        ax.plot(np.arange(5) + l*x_offset, 5+rand(5) + k*y_offset,
                'r-o', ms=1, mew=0, mfc='r')
        ax.plot(np.arange(5) + l*x_offset, 3+rand(5) + k*y_offset,
                'b-o', ms=1, mew=0, mfc='b')
        ax.annotate('K={},L={}'.format(k, l), (2.5+ (k)*x_offset,l*y_offset), size=3,ha='center')
plt.savefig(os.path.join(os.getcwd(), 'plot-average.pdf'))

print 'Final plot created.'

大约需要一两秒钟的时间运行。我认为所有的时间都花在了设置相当复杂的axes对象上。

使用虚假数据的输出结果

1
非常好。只是出于好奇,这里提到的技术链接也可以使用吗?只使用线条的set_ydata方法。不过应该找到一种复制ax对象的方法。 - rowman
@rowman,您能具体说明一下链接中的哪个方法吗?如果您想制作400个单独的图形,则set_ydata会很有用,但我不认为它在这种情况下会有用。 - tacaswell
对于GUI应用程序,我只需创建一条线并仅更新Y以提高速度,而不是每次重新绘制整个图形。在这种情况下,我只是考虑复制一个对象400次,更新Y和图形轴的位置,而不是创建400个图形。尽管可能需要相同的时间。 - rowman
1
@rowman 请参考 http://docs.python.org/library/copy.html 。我不确定速度。但是您仍然需要手动设置网格,因为figure中的axes位置是axes的属性。 - tacaswell

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接