如何对 matplotlib 中的二维数组数据使用 line.set_data?

How to use line.set_data for data that is a 2 dimensional array in matplotlib?

我正在尝试在 matplotlib 中同时为多条线设置动画。为此,我遵循 matplotlib.animation 文档中的教程:

https://matplotlib.org/stable/api/animation_api.html

本教程的想法是创建一条线 ln, = plt.plot([], []) 并使用 ln.set_data 更新该线的数据以制作动画。虽然当线数据是 n 个数据点的一维数组 (shape = (n,)) 时一切正常,但当线数据是二维数组 (shape = (n,k)) 时我遇到了麻烦要绘制的 k 行。

更准确地说,plt.plot 接受数组作为输入,每一列对应一条要绘制的新线。这是一个简单的例子,用一个 plt.plot 调用绘制了 3 条线:

import matplotlib.pyplot as plt
import numpy as np


x = np.linspace(0, 2 * np.pi, 100).reshape(-1, 1)
x = np.concatenate([x] * 3, axis=1)

# generate 3 curves
y = np.copy(x)
y[:, 0] = np.cos(y[:, 0])
y[:, 1] = np.sin(y[:, 1] )
y[:, 2] = np.sin(y[:, 2] ) + np.cos(y[:, 2])

fig, ax = plt.subplots()
plt.plot(x,y)
plt.show()

但是,如果我尝试根据生成动画的需要使用 .set_data 设置数据,我会遇到问题:

import matplotlib.pyplot as plt
import numpy as np


x = np.linspace(0, 2 * np.pi, 100).reshape(-1, 1)
x = np.concatenate([x] * 3, axis=1)

# generate 3 curves
y = np.copy(x)
y[:, 0] = np.cos(y[:, 0])
y[:, 1] = np.sin(y[:, 1] )
y[:, 2] = np.sin(y[:, 2] ) + np.cos(y[:, 2])

fig, ax = plt.subplots()
p, = plt.plot([], [], color='b')
p.set_data(x, y)
plt.show()

有没有办法 set_data 二维数组?虽然我知道我可以只创建三个图 p1, p2, p3 并在循环中对每个图调用 set_data,但我的真实数据包含 1000-10,000 行要绘制,这使得动画速度太慢.

非常感谢您的帮助。

set_data()给出的数组将是两个一维数组,所以在这种情况下需要三个set_data()。

import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
import numpy as np

x = np.linspace(0, 2 * np.pi, 100).reshape(-1, 1)
x = np.concatenate([x] * 3, axis=1)

# generate 3 curves
y = np.copy(x)
y[:, 0] = np.cos(y[:, 0])
y[:, 1] = np.sin(y[:, 1] )
y[:, 2] = np.sin(y[:, 2] ) + np.cos(y[:, 2])

fig, ax = plt.subplots()
ax = plt.axes(xlim=(0,6), ylim=(-1.5, 1.5))
line1, = ax.plot([], [], lw=2)
line2, = ax.plot([], [], lw=2)
line3, = ax.plot([], [], lw=2)


def animate(i):
    line1.set_data(x[:i, 0], y[:i, 0])
    line2.set_data(x[:i, 1], y[:i, 1])
    line3.set_data(x[:i, 2], y[:i, 2])
    return line1,line2,line3

anim = FuncAnimation(fig, animate, frames=100, interval=200, repeat=False)
plt.show()

一种方法是创建一个 Line2D 对象列表并在循环中使用 set_data。请注意,ax.plot() 总是 returns 线条列表,即使只绘制了一条线条。

import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
import numpy as np

x = np.linspace(0, 2 * np.pi, 100)

# generate 10 curves
y = np.sin(x.reshape(-1, 1) + np.random.uniform(0, 2 * np.pi, (1, 10)))

fig, ax = plt.subplots()
ax.set(xlim=(0, 2 * np.pi), ylim=(-1.5, 1.5))
# lines = [ax.plot([], [], lw=2)[0] for _ in range(y.shape[1])]
lines = ax.plot(np.empty((0, y.shape[1])), np.empty((0, y.shape[1])), lw=2)

def animate(i):
    for line_k, y_k in zip(lines, y.T):
        line_k.set_data(x[:i], y_k[:i])
    return lines

anim = FuncAnimation(fig, animate, frames=x.size, interval=200, repeat=False)
plt.show()