Home > Back-end >  How do I redraw my bar plot without keeping the previous one?
How do I redraw my bar plot without keeping the previous one?

Time:03-26

I've made an animation in which the blue bars get updated from frame to frame. The problem is that the bars from the previous iteration stay on the canvas without being removed. How do I make the iterative plotting non-additive (non-overlapping frames like in a gif that updates everything from frame to frame)?

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
from matplotlib.ticker import AutoMinorLocator, MaxNLocator


def count_elements(iterable):

    val_dict = {}

    val_list = list(iterable)

    for i in set(val_list):
        val_dict.update({i:val_list.count(i)})

    return np.array(list(val_dict.keys())),np.array(list(val_dict.values()))


# Generate n rolls for a probability distribution of two spins of a wheel of fortune that has 4 equally large wedges. The wedges have numbers from one to 4 on them.
p = 0.25
prob_dist = np.array([[2,3,4,5,6,7,8],[p*p,2*p*p,3*p*p,4*p*p,3*p*p,2*p*p,p*p]])
mu = sum([prob_dist[0,i]*prob_dist[1,i] for i in range(prob_dist.shape[1])])
sig = sum([prob_dist[1,i]*(prob_dist[0,i]-mu)*(prob_dist[0,i]-mu) for i in range(prob_dist.shape[1])])

# true distribution
fig, ax = plt.subplots(figsize=(7,4)) 
ax.bar(prob_dist[0], prob_dist[1], width=0.5, align="center", ec=None, color='red', alpha=0.5)

# Experimental data
n = 10
rolls = np.random.randint(1,5,n)   np.random.randint(1,5,n)
exp_vals, exp_count = count_elements(rolls)
ax.bar(exp_vals,exp_count/n, width=0.3, align="center", ec=None, color='blue', alpha=0.5)



def update(frame):

    n = int(10 *1**frame)
    rolls = np.random.randint(1,5,n)   np.random.randint(1,5,n)
    exp_vals, exp_count = count_elements(rolls)

    ax.bar(exp_vals,exp_count/n, width=0.3, align="center", ec=None, color='blue', alpha=0.5)

    

ani = FuncAnimation(fig, update, frames=range(1,10),repeat=False,blit=False,interval=1000)
plt.show()

CodePudding user response:

It seems you only update the height of the bars, so you should do exactly that - update the heights of the bars:

...    
# true distribution
fig, ax = plt.subplots(figsize=(7,4)) 
ax.bar(prob_dist[0], prob_dist[1], width=0.5, align="center", ec=None, color='red', alpha=0.5)
#store the x-values
all_x_vals = prob_dist[0]

#catch the bar container for the update in the animation loop
bc = ax.bar(all_x_vals, 0, width=0.3, align="center", ec=None, color='blue', alpha=0.5)

def update(frame):
    #not sure what this is as it will always be 10
    n = int(10 *1**frame)
    rolls = np.random.randint(1,5,n)   np.random.randint(1,5,n)
    exp_vals, exp_count = count_elements(rolls)
        
    heights = np.zeros_like(all_x_vals)
    heights[np.in1d(all_x_vals, exp_vals).nonzero()[0]] = exp_count/n

    for b, h in zip(bc, heights):
        b.set_height(h) 
    
    #sanity check, should be 1
    #print(sum(b.get_height() for b in bc))
  
ani = FuncAnimation(fig, update, frames=range(0,10),repeat=False,blit=False,interval=1000)
plt.show()
  • Related