实时更新matplotlib条形图

0 人关注

我正在编写泡沫排序算法,它接收一个随机的整数列表,按递增的顺序排序,并将排序后的整数列表绘制成柱状图的Y值。我的第一个条形图是未排序的列表,第二个是已排序的列表。

我希望图表能够实时更新。我将通过向matplotlib提供排序越来越多的列表来实现这一点。(即每次都是新的列表)

我查了很多关于在matplotlib中更新图表的教程,但它们大多是针对像散点图那样的,一次只添加一个点。我还看到 更新一个matplotlib的条形图? 但我一生都无法理解它......。

那么,我怎样才能使这个条形图实时更新呢?谢谢你!"。

我的代码如下。你可以忽略排序的算法。你所需要知道的是,它返回一个排序后的数字列表,其形式为[1, 2, 3, 4, 5]。

import random
import matplotlib.pyplot as plt
import numpy as np
print("bubble sort")
plt.style.use('fivethirtyeight')
n = int(input("How many items would you like to sort? "))
list_num = np.random.randint(0,500, n)
orig_list_num = list_num.copy()
def is_sorted(list_num):
  Flag = True
  while Flag == True:
    Flag=False
    for i in range(0, (len(list_num))-j):
      if i+1 >= len(list_num):
        break
      if list_num[i] > list_num[i+1]:
        tempvar=list_num[i]
        list_num[i] = list_num[i+1]
        list_num[i+1] = tempvar
        Flag=True
  return list_num
list_num = is_sorted(list_num)
#unsorted graph
indices = np.arange(n)
plt.subplot(1, 2, 1)
plt.bar(indices, orig_list_num)
plt.xlabel("Unsorted")
#sorted graph
plt.subplot(1, 2, 2)
plt.bar(indices, list_num)
plt.xlabel("Sorted")
plt.show()
    
4 个评论
Bill
你是否看了 matplotlib.animation ?
一次增加一个点的例子有什么问题?也许它可以一次增加100个新的点,也可以一次删除100个旧的点--所以它可以一次替换所有的点--你只能尝试。
Updating a matplotlib bar graph? 中的例子使用了这样一个事实:它可以建立在 tkinter 上GUI - 所以它使用 tkinter 的函数来更新GUI。但是 matplotlit 可能会使用不同的GUI,那么这个例子就不能工作了。
如果你从 plt 中得到了 ax ,那么你应该可以访问 ax.data 中的所有数值--然后你可以替换它们。你可能还需要运行 update() 来更新屏幕上的情节。
python
matplotlib
user15780499
user15780499
发布于 2021-04-28
1 个回答
furas
furas
发布于 2021-04-28
已采纳
0 人赞同

It is first version without 趣味动画 为动画。它可能很慢。
而且在动画结束前关闭窗口可能会有问题。

First I use

plt.show(block=False) 

以显示绘图,而不阻断代码

接下来我运行is_sorted()来更新情节。

Inside is_sorted() I use

plt.cla() 

to clear last drawn axis

现在我可以在同一个地方再次画出bar,但有新的数据。

plt.bar(indices, list_num)

之后,我放慢了代码的速度,这样它就有时间在窗口中显示情节了

plt.pause(0.01)

如果没有pause,可能会显示空窗口。

if you use -1 in (len(list_num))-j-1 then you don't need if i+1 >= len(list_num): break

import random
import matplotlib.pyplot as plt
import numpy as np
# --- functions --
def is_sorted(list_num):
    flag = True
    j = -1
    while flag:
        flag = False
        j += 1
        for i in range(0, (len(list_num))-j-1):
            if list_num[i] > list_num[i+1]:
                # in Python you can do it without `tempvar`
                list_num[i], list_num[i+1] = list_num[i+1], list_num[i]
                flag = True
                plt.cla()
                plt.bar(indices, list_num)
                plt.pause(0.01)
            if closed:
                flag = False
                break  # it exits `for`-loop but not `while`-loop and I need `flag = False` 
def on_close(event):
    global closed   # to assign value to external variable which I need in `is_sorted
    closed = True
    print('Closing window')
# --- main ---
closed = False  # default value at start
print("bubble sort")
plt.style.use('fivethirtyeight')
#n = int(input("How many items would you like to sort? "))
n = 20
list_num = np.random.randint(0, 500, n)
orig_list_num = list_num.copy()
indices = np.arange(n)
#unsorted graph
plt.subplot(1, 2, 1)
plt.bar(indices, orig_list_num)
plt.xlabel("Unsorted")
#sorted graph
plt.subplot(1, 2, 2)
plt.bar(indices, list_num)
plt.xlabel("Sorted")
plt.ion() # `Interaction ON` siliar to `block=False`
#plt.show(block=False)
# assign function to plot
fig = plt.gcf()
fig.canvas.mpl_connect('close_event', on_close)
is_sorted(list_num)
input("Press ENTER to exit")

EDIT:

使用你的链接中的想法,我创建了第二个版本--我认为它可以运行得更快一些,但我期望有更好的速度。

在这个版本中,我把酒吧分配给变量

bar2 = plt.bar(indices, list_num)

这样以后我就可以不用再画画了,就可以把酒吧的高度提高了。

bar2[i].set_height(list_num[i])
bar2[i+1].set_height(list_num[i+1])
import random
import matplotlib.pyplot as plt
import numpy as np
# --- functions --
def is_sorted(list_num):
    flag = True
    j = -1
    while flag:
        flag = False
        j += 1
        for i in range(0, (len(list_num))-j-1):
            if list_num[i] > list_num[i+1]:
                # in Python you can do it without `tempvar`
                list_num[i], list_num[i+1] = list_num[i+1], list_num[i]
                flag = True
                # replace all values
                #for rect, value in zip(bar2, list_num):
                #    rect.set_height(value)
                # replace only two new values
                bar2[i].set_height(list_num[i])
                bar2[i+1].set_height(list_num[i+1])
                plt.pause(0.001)
            if closed:
                flag = False
                break  # it exits `for`-loop but not `while`-loop and I need `flag = False` 
def on_close(event):
    global closed   # to assign value to external variable which I need in `is_sorted
    closed = True
    print('Closing window')
# --- main ---
closed = False  # default value at start
print("bubble sort")
plt.style.use('fivethirtyeight')
#n = int(input("How many items would you like to sort? "))
n = 20
list_num = np.random.randint(0, 500, n)
orig_list_num = list_num.copy()
indices = np.arange(n)
#unsorted graph
plt.subplot(1, 2, 1)
plt.bar(indices, orig_list_num)
plt.xlabel("Unsorted")
#sorted graph
plt.subplot(1, 2, 2)
bar2 = plt.bar(indices, list_num)
plt.xlabel("Sorted")
plt.ion() # `Interaction ON` siliar to `block=False`
#plt.show(block=False)
# assign function to plot
fig = plt.gcf()
fig.canvas.mpl_connect('close_event', on_close)
is_sorted(list_num)
input("Press ENTER to exit")