为什么使用Matplotlib绘图如此缓慢?

我目前正在评估不同的python绘图库。现在我正在尝试matplotlib,我对它的性能非常失望。下面的示例是从SciPy示例修改而来的,每秒仅提供~8帧

有没有加快速度的方法,或者我应该选择一个不同的绘图库

pylab导入的

*
导入时间
离子()
图=图()
ax1=图add_子批次(611)
ax2=图add_子批次(612)
ax3=图添加子批次(613)
ax4=图添加子批次(614)
ax5=图add_子批次(615)
ax6=图添加子批次(616)
x=arange(0,2*pi,0.01)
y=sin(x)
第1行,=ax1.绘图(x,y,'r-')
第2行,=ax2.绘图(x,y,'g-')
第3行,=ax3.绘图(x,y,'y-')
第4行,=ax4.绘图(x,y,'m-')
第5行,=ax5.绘图(x,y,'k-')
第6行,=ax6.绘图(x,y,'p-')
#关闭交互式打印-将速度提高1帧/秒
plt.ioff()
tstart=time.time()#用于分析
对于我在arange(1200):
第1行设置数据(sin(x+i/10.0))#更新数据
第2行设置数据(sin(2*x+i/10.0))
第3行设置数据(sin(3*x+i/10.0))
第4行设置数据(sin(4*x+i/10.0))
第5行设置数据(sin(5*x+i/10.0))
第6行设置数据(sin(6*x+i/10.0))
draw()#重新绘制画布
打印“FPS:”,200/(time.time()-tstart)

首先,(尽管这不会改变性能)考虑清理代码,类似于:

将matplotlib.pyplot导入为plt
将numpy作为np导入
导入时间
x=np.arange(0,2*np.pi,0.01)
y=np.sin(x)
图,轴=plt子批次(nrows=6)
样式=['r-'、'g-'、'y-'、'm-'、'k-'、'c-']
线条=[ax.plot(x,y,style)[0]对于ax,zip中的样式(轴,样式)]
图2(图3)
tstart=time.time()
对于x范围内的i(1,20):
对于j,枚举中的行(行,开始=1):
线集数据(np.sin(j*x+i/10.0))
图canvas.draw()
打印“FPS:”,20/(time.time()-tstart)

在上面的例子中,我得到大约10fps

请注意,根据具体的用例,matplotlib可能不是一个很好的选择。它面向出版物质量数据,而不是实时显示

但是,您可以做很多事情来加速这个示例

有两个主要的原因,为什么这是缓慢的,因为它是

1) 调用fig.canvas.draw()。这是你的瓶颈。在您的情况下,不需要重新绘制轴边界、记号标签等

2) 在你的例子中,有很多子地块,有很多勾号标签。这些画要花很长时间

这两个问题都可以通过使用blitting来解决

为了有效地执行blitting,您必须使用特定于后端的代码。在实践中,如果您真的担心平滑的动画,您通常会在某种gui工具包中嵌入matplotlib绘图,所以这不是什么大问题

但是,如果我不知道你在做什么,我就帮不了你

尽管如此,仍然有一种相当快速的方式

将matplotlib.pyplot导入为plt
将numpy作为np导入
导入时间
x=np.arange(0,2*np.pi,0.1)
y=np.sin(x)
图,轴=plt子批次(nrows=6)
图2(图3)
#我们需要在开始制作动画之前画画布。。。
图canvas.draw()
样式=['r-'、'g-'、'y-'、'm-'、'k-'、'c-']
def绘图(ax,样式):
返回ax.plot(x,y,style,animated=True)[0]
lines=[打印(ax,样式)用于ax,zip中的样式(轴,样式)]
#让我们捕捉这个人物的背景
背景=[图canvas.copy_from_bbox(ax.bbox)for ax in axs]
tstart=time.time()
对于X范围内的i(1,2000):
项目=枚举(zip(线、轴、背景),开始=1)
对于项目中的j,(行、轴、背景):
图canvas.restore_区域(背景)
线集数据(np.sin(j*x+i/10.0))
ax.draw_艺术家(线条)
图帆布布利特(ax.bbox)
打印'FPS:',2000/(time.time()-tstart)

这给了我大约200fps

为了方便起见,matplotlib的最新版本中有一个动画模块

例如:

将matplotlib.pyplot导入为plt
将matplotlib.animation导入为动画
将numpy作为np导入
x=np.arange(0,2*np.pi,0.1)
y=np.sin(x)
图,轴=plt子批次(nrows=6)
样式=['r-'、'g-'、'y-'、'm-'、'k-'、'c-']
def绘图(ax,样式):
返回ax.plot(x,y,style,animated=True)[0]
lines=[打印(ax,样式)用于ax,zip中的样式(轴,样式)]
定义动画(i):
对于j,枚举中的行(行,开始=1):
线集数据(np.sin(j*x+i/10.0))
回程线
#我们通常会在这里指定一个合理的“间隔”。。。
ani=animation.FuncAnimation(图,animate,xrange(1200),
间隔=0,blit=真)
plt.show()

发表评论