Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Interactive bar plot using matplotlib with annotation change

I'm trying to create a horizontal bar plot that can dynamically change with a slider. I've followed the recipe on the matplotib website and it works well for line data. The code:

def interactive_pyramid(ages_matrix, year_labels):
    fig, axs = plt.subplots()
    plt.subplots_adjust(bottom=0.25)
    l, = axs.plot(range(len(ages_matrix[0, :])), ages_matrix[0, :])
    axs.annotate(year_labels[0], xy=(0.85, 0.85), xycoords="axes fraction")
    axs.set_ylim([0,800])

    pprint (dir(axs))
    axcolor = 'lightgoldenrodyellow'
    axyear = plt.axes([0.25, 0.1, 0.5, 0.1], axisbg=axcolor)
    syear = Slider(axyear, 'Year', 0, ages_matrix.shape[0] - 1, 0)

    def update(val):
        year = syear.val
        # axs.barh(range(len(ages_matrix[0, :])), ages_matrix[val, :])
        l.set_ydata(ages_matrix[val, :])
        # axs.annotate(year_labels[year], xy=(0.85, 0.85), xycoords="axes fraction")
        axs.Annotation.remove()
        fig.canvas.draw()
    syear.on_changed(update)

ages_matrix is a 2d ndarray and year_labels is a 1d ndarray

two main questions:

  • the axs.barh() does not return an object with a set_ydata() method do I can't change the y data. if I just draw the data again on the axs object it doesn't erase the previous information, resulting in a clutter of charts.
  • the same happens with annotations - it does not erase the previous one.

Is there any way to efficiently erase the ax and draw it again? maybe some way to refresh the canvas?

Clutter

like image 566
DeanLa Avatar asked Feb 17 '26 03:02

DeanLa


1 Answers

That's what I came up with:

# Init Chart
fig, axs = plt.subplots()
plt.subplots_adjust(bottom=0.25)
axs.set_xlim([0,ages_matrix.max()*1.05])
# Initial Pyramid
pyramid = axs.barh(np.arange(len(ages_matrix[0, :])) * 5,
                   ages_matrix[0, :],
                   height=4.5)
# Annotation
ann = axs.annotate(year_labels[0], xy=(0.85, 0.85), xycoords="axes fraction")
# Slider
axcolor = 'lightgoldenrodyellow'
axyear = plt.axes([0.25, 0.1, 0.5, 0.1], axisbg=axcolor)
syear = Slider(axyear, 'Year', 0, ages_matrix.shape[0] - 1, 0)

def update(val):
    t = syear.val
    year = np.trunc(year_labels[t])
    day = (year_labels[t] - year) * 365
    ages = ages_matrix[t, :]
    for i, p in enumerate(pyramid):
        p.set_width(ages[i])
    ann.set_text("Year: {}\nDay: {}".format(int(year), int(day)))
    fig.canvas.draw()

enter image description here

like image 60
DeanLa Avatar answered Feb 18 '26 17:02

DeanLa



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!