Python 实时更新matplotlib条形图

Python 实时更新matplotlib条形图,python,matplotlib,Python,Matplotlib,我正在编写冒泡排序算法,它接受一个随机整数列表,按递增顺序排序,并将排序后的整数列表绘制为条形图的y值。我的第一个条形图是未排序的列表,第二个是已排序的列表 我想让图表实时更新。我会通过提供排序越来越多的matplotlib列表来实现这一点。(即每次都有新的名单) 我在matplotlib中查阅了许多关于更新图表的教程,但它们大多是针对散点图这样的教程,在散点图中一次添加一个点。我也见过,但我一生都无法理解 那么,我该如何实时更新这个条形图呢?谢谢大家! 我的代码如下。您可以忽略排序算法。您需要

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

我想让图表实时更新。我会通过提供排序越来越多的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
  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()

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

首先我使用

plt.show(block=False) 
显示无阻塞代码的绘图

接下来我运行
is_sorted()
来更新绘图

内部
已排序()
我使用

plt.cla() 
清除上次绘制的轴的步骤

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

plt.bar(indices, list_num)
之后,我减慢代码的速度,以便有时间在窗口中显示绘图

plt.pause(0.01)
如果不暂停,则可能会显示空窗口


顺便说一句:

如果在
(len(list_num))-j-1中使用
-1
,那么如果i+1>=len(list_num):break



编辑:

使用你们链接中的想法,我创建了第二个版本——我认为它可以运行得更快一点,但我希望速度会更好

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

bar2 = plt.bar(indices, list_num)
所以以后我不用再画了,就可以查根杆高了

bar2[i].set_height(list_num[i])
bar2[i+1].set_height(list_num[i+1])


我正在考虑使用
FuncAnimation
的版本,但它需要做很多更改。它需要创建使用单个
进行
-循环的代码,而
+
进行
-循环,然后
FuncAnimation
将重复此
进行
-循环

我有其他想法-在
plt.plot()
中,可以用
ax.set_ydata()
替换绘图中的数据,但是
plt.bar()
没有此功能。但是
set\u height()
似乎类似



在回答问题时,我直接在
tkinter
中创建了动画,而没有
matplotlib

您看过吗?一次添加一个点的示例有什么问题?可能它可以在当时添加100个新点,也可以在当时删除100个旧点-因此它可以在当时替换所有点-您只需尝试一下。例如,在更新matplotlib条形图中?
使用了一个事实,即它可以构建在
tkinter
GUI上-因此它使用
tkinter
函数来更新GUI。但是
matplotlit
可能使用不同的GUI,因此此示例将不起作用。如果您从
plt
获取
ax
,则您应该可以使用绘图中的所有值访问
ax.data
,然后可以替换它们。您可能还需要运行
update()
来更新屏幕上的绘图。
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")