使用MatPlotLib绘制连续数据流的图表

5
我想使用MatPlotLib绘制一个图表,这个图表会随着时间的推移而变化。在每个时间步骤中,将添加一个附加数据点到图表中。但是,应该只显示一个图表,其外观随时间演变。
在我的测试示例中,图表是一个简单的线性图(y = x)。以下是我尝试过的内容:
for i in range(100):
    x = range(i)
    y = range(i)
    plt.plot(x, y)
    plt.ion()
    plt.show()
    time.sleep(1)

然而,这里发生的是创建了多个窗口,所以在循环结束时我有100个窗口。同时,我还注意到对于最近的窗口,它仅是一个白色窗口,绘图仅在下一步才会出现。
因此,我的两个问题是:
1)我应该如何更改我的代码,以便只显示一个窗口,其内容随时间变化而变化?
2)我应该如何更改我的代码,以便在最新的时间步长中,图表实际上显示在窗口中,而不是仅显示白色窗口?
谢谢!

可能是Dynamically updating plot in matplotlib的重复问题。 - Diziet Asahi
3个回答

9

(1)

您可以在开始处设置 plt.ion() 并将所有图形绘制到同一窗口中。在循环内使用 plt.draw() 显示图形,使用 plt.pause(t) 使其停顿。请注意,t 可能非常小,但命令需要存在才能使动画在大多数后端中正常工作。
您可能想要在绘制新内容之前清除轴,可以使用 plt.gca().cla()

import matplotlib.pyplot as plt

plt.ion()
for i in range(100):
    x = range(i)
    y = range(i)
    # plt.gca().cla() # optionally clear axes
    plt.plot(x, y)
    plt.title(str(i))
    plt.draw()
    plt.pause(0.1)

plt.show(block=True) # block=True lets the window stay open at the end of the animation.

除了这种非常简单的方法,您还可以使用http://matplotlib.org/examples/animation/index.html中提供的任何动画示例。

(2)

为了在新窗口中获得每个绘图,请使用plt.figure()并删除plt.ion()。同时只在最后显示窗口:

import matplotlib.pyplot as plt

for i in range(100):
    x = range(i)
    y = range(i)
    plt.figure()
    plt.plot(x, y)
    plt.title(str(i))
    
plt.show()

请注意,您可能会发现在这两种情况下第一个图形为空,因为对于i=0range(i) == []是一个没有任何点的空列表。即使对于i=1,也只有一个点被绘制,但显然没有线可以将一个单独的点连接到自身。

另外,如果你在for循环之外调用plt.figure(),它会以类似于上面显示的plt.ion()方法的方式工作,唯一不同的是在脚本的其余部分运行之前,你不必关闭图形(就像我在2.7版本中必须这样做)。 - user6565699
@FeeJF 抱歉,我不太明白你的意思。如果你在循环外调用 plt.figure(),那么只会有一个窗口,没有任何动画效果。 - ImportanceOfBeingErnest

1

这里有一种我发现非常有效的方法。

你需要这个包。

from IPython.display import clear_output

%matplotlib inline
import matplotlib.pyplot as plt

clear_output清除笔记本的输出。

def plot_graph(list_of_points: list):
    clear_output(wait=True)
    plt.figure(figsize=(15, 10), linewidth=2, edgecolor='steelblue', facecolor='skyblue')
    plt.subplots_adjust(left=0.20, bottom=0.20)
    ax = plt.gca()
    ax.set_xlim([0, max_x])
    plt.plot(list_of_points, label="Points")
    plt.legend()
    plt.show()

这个函数接受一个点列表,清除单元格的输出并绘制新的图形。

您可以将其放在一个 for 循环中,类似于以下代码:

points = []
for i in range(10):
    points.append(i + random.randint(0, 9))
    plot_graph(points, 10)

它应该看起来像这样。

Animated Graph

我并不是说这是唯一的方法,但它很简单,我可以理解和编辑,并且能够顺利完成我的工作。

编辑 我添加了plt.legend()来显示图表的名称,由于此操作是在创建gif之后进行的,所以在gif中不会显示。


1

我认为最好的方法是创建一条折线图,然后在其中更新数据。这样你就可以拥有单个窗口和单个图形,它们将不断更新。

import matplotlib.pyplot as plt

plt.ion()
fig = plt.figure(figsize=(16,8))
axes = fig.add_subplot(111)
data_plot=plt.plot(0,0)
line, = axes.plot([],[])
for i in range(100):
    x = range(i)
    y = range(i)
    line.set_ydata(y)
    line.set_xdata(x)
    if len(y)>0:
        axes.set_ylim(min(y),max(y)+1) # +1 to avoid singular transformation warning
        axes.set_xlim(min(x),max(x)+1)
    plt.title(str(i))
    plt.draw()
    plt.pause(0.1)

plt.show(block=True)

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