【问题标题】:Updating matplotlib bar chart in real time实时更新matplotlib条形图
【发布时间】:2021-04-28 01:05:19
【问题描述】:

我正在编写冒泡排序算法,它接收一个随机整数列表,按升序对它们进行排序,并将排序后的整数列表绘制为条形图的 y 值。我的第一个条形图是未排序的列表,第二个是已排序的。

我希望图表实时更新。我会通过提供排序越来越多的 matplotlib 列表来做到这一点。 (即每次都有新列表)

我查阅了很多关于在 matplotlib 中更新图表的教程,但它们主要用于像散点图这样一次添加一个点的教程。我也见过Updating a matplotlib bar graph?,但我这辈子都看不懂……

那么,我将如何实时更新此条形图?谢谢!

我的代码如下。您可以忽略排序算法。您只需要知道它以 [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
  j=-1
  while Flag == True:
    Flag=False
    j+=1
    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()

【问题讨论】:

  • 你看过matplotlib.animation吗?
  • 每次添加一个点的示例有什么问题?可能它可以同时添加 100 个新点并同时删除 100 个旧点 - 因此它可以同时替换所有点 - 你只需尝试一下。
  • Updating a matplotlib bar graph? 中的示例使用它可以构建在tkinter GUI 上的事实 - 所以它使用tkinter 函数来更新 GUI。但是matplotlit 可能使用不同的 GUI,然后这个例子就不起作用了。
  • 如果你从plt 得到ax,那么你应该可以访问ax.data 中的所有值 - 然后你可以替换它们。您可能还需要运行 update() 来更新屏幕上的绘图。

标签: python matplotlib


【解决方案1】:

这是第一个没有FuncAnimation 动画的版本。它可能很慢。
并且在动画结束之前关闭窗口可能会有问题。

首先我使用

plt.show(block=False) 

在不阻塞代码的情况下显示图

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

is_sorted()里面我用

plt.cla() 

clear last drawn axis

现在我可以用新数据在同一个地方再次绘制bar

plt.bar(indices, list_num)

之后我放慢代码速度,以便有时间在窗口中显示绘图

plt.pause(0.01)

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


顺便说一句:

如果您在(len(list_num))-j-1 中使用-1,则不需要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")

编辑:

使用您链接中的想法,我创建了第二个版本 - 我认为它可以运行得更快,但我预计速度会更快。

在这个版本中,我将 bar 分配给变量

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")

我正在考虑使用 FuncAnimation 的版本,但它需要更改很多 cod。它需要创建使用单个 for-loop 而不是 while+for 的代码 - 然后 FuncAnimation 将重复代码而不是 for-loop。

我有其他想法 - 在plt.plot() 中,您可以用ax.set_ydata() 替换绘图数据,但plt.bar() 没有此功能。但set_height() 似乎很相似。


在回答How do I correctly implement a bubble sort algorithm in python tkinter? 的问题时,我直接在tkinter 中创建了动画,而没有matplotlib

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-03-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-12-24
    • 1970-01-01
    • 1970-01-01
    • 2020-08-04
    相关资源
    最近更新 更多