如何对 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()
我正在尝试在 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()