Python, Matplotlib:绘制多条线(数组)和动画

5
我开始学习Python编程(和面向对象编程),但我有Fortran(90/95)和Matlab编程的扎实经验。
我正在使用tkinter环境开发一个小工具,使用动画来展示多条线(一个数据数组而不是向量)。 以下是我问题的简单示例。 我不明白为什么这两种绘制数据的方式结果如此不同?
from pylab import *

Nx=10
Ny=20

xx   = zeros( ( Nx,Ny) )
data = zeros( ( Nx,Ny) )

for ii in range(0,Nx):
    for jj in range(0,Ny):
        xx[ii,jj]   = ii
        data[ii,jj] = jj


dline = plot(xx,data)

mline, = plot([],[])
mline.set_data(xx.T,data.T)

show()

如果你只绘制"dline",每条线都会单独绘制并使用不同的颜色。 如果你只绘制"mline",所有线条都会链接在一起且只有一种颜色。

我的目标是使用"mline"创建一个动画,在每个循环中更改数据。 这是一个简单的源代码,说明了我的目的:

from pylab import *
from matplotlib import animation

Nx=10
Ny=20

fig = plt.figure()
fig.set_dpi(100)
fig.set_size_inches(7, 6.5)

ax = plt.axes(xlim=(0, Nx), ylim=(0, Ny))

xx   = zeros( ( Nx,Ny) )
data = zeros( ( Nx,Ny) )
odata = zeros( ( Nx,Ny) )

for ii in range(0,Nx):
    for jj in range(0,Ny):
        xx[ii,jj]    = ii
        odata[ii,jj] = jj
        data[ii,jj]  = 0.

#dline = plot(xx,odata)

mline, = plot([],[])

def init():
    mline.set_data([],[])
    return mline,

def animate(coef):
   for ii in range(0,Nx):
        for jj in range(0,Ny):
            data[ii,jj] = odata[ii,jj] * (1.-float(coef)/360.)

   mline.set_data(xx.T,data.T)
   return mline,

anim = animation.FuncAnimation(fig, animate, 
                               init_func=init, 
                               frames=360, 
                               interval=5,
                               blit=True)

plt.show()

我希望我已经清楚地表达了我的问题。

谢谢, 尼古拉斯。


2
如果您将2D数据传递给“plt.plot()”,它将被转换为单独的项,因此“dline”是包含20个单独线条对象的列表。您的“mline”只是一个单独的线条对象。如果您将2D数据传递给它,数据将被展平,就像使用“dline = ax.plot(xx.flat, data.flat)”一样。 - Rutger Kassies
感谢Rutger Kassies的帮助。我在下面发布了我的问题解决方案。 - Ngrigri
2个回答

5
正如@Rutger Kassies在评论中指出的那样,
dline = plot(xx,data)

这段代码在输入数据中进行了一些神奇的解析,将您的数组分成了许多x-y对,并将它们绘制出来。请注意,dline是一个列表,其中包含了许多Line2D对象。

mline, = plot([],[])
mline.set_data(xx.T,data.T)

您正在创建单个Line2D对象,库尽力将2D数据塞入1D绘图对象中,并通过压缩输入来实现。

要动画显示N条线,您只需要NLine2D对象:

lines = [plot([],[])[0] for j in range(Ny)] # make a whole bunch of lines

def init():
    for mline in lines:
        mline.set_data([],[])
    return lines

def animate(coef):
   data = odata * (1.-float(coef)/360.)
   for mline, x, d in zip(lines, data.T, xx.T):
       mline.set_data(x, d)
   return lines

您不需要预分配data,而且在 Python 中循环的速度比让numpy为您执行要慢得多。


感谢tcaswell的帮助。我的问题解决方案已在下面发布。 - Ngrigri

0
感谢Rutger Kassies和tcaswell。 这里是与上面相同的示例,但现在它按照我的要求工作。 我希望它能帮助其他Python程序员。
from pylab import *
from matplotlib import animation

Nx=10
Ny=20

fig = plt.figure()
fig.set_dpi(100)
fig.set_size_inches(7, 6.5)
axis([0, Nx-1, 0, Ny])

xx    = zeros( ( Nx,Ny) )
data  = zeros( ( Nx,Ny) )
odata = zeros( ( Nx,Ny) )

for ii in range(0,Nx):
    xx[ii,:]    = float(ii)

for jj in range(0,Ny):
    odata[:,jj] = float(jj)

#dline = plot(xx,odata)

lines = [plot([],[])[0] for j in range(Ny)] # make a whole bunch of lines


def init():
    for mline in lines:
        mline.set_data([],[])
    return lines

def animate(coef):

   data = odata * (1.-float(coef)/360.)

   for mline, x, d in zip(lines, xx.T, data.T,):
       mline.set_data(x, d)

   return lines

anim = animation.FuncAnimation(fig, animate, 
                               init_func=init, 
                               frames=360, 
                               interval=5,
                               blit=True)

plt.show()

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