I would like to animate a fitness function graph to debug my algorithm behavior. However, as soon as the plot is added to the page, it becomes a static image and no longer refreshes.
Any ideas on how to animate a line chart?
I also couldn’t find if I can reuse a plot slot to manually set a new graph.
import matplotlib.pyplot as plt
import matplotlib.animation as animation
import numpy as np
import streamlit as st
fig, ax = plt.subplots()
max_x = 5
max_rand = 10
x = np.arange(0, max_x)
ax.set_ylim(0, max_rand)
line, = ax.plot(x, np.random.randint(0, max_rand, max_x))
def init(): # give a clean slate to start
line.set_ydata([np.nan] * len(x))
return line,
def animate(i): # update the y values (every 1000ms)
line.set_ydata(np.random.randint(0, max_rand, max_x))
return line,
ani = animation.FuncAnimation(
fig, animate, init_func=init, interval=1000, blit=True, save_count=10)
st.pyplot(plt)
Thanks for the response, works beautifully. Would you consider adding some documentation on working with charts? I couldn’t figure how to update charts from the source code or code examples.
Hey @cristian.cotoi, thanks for the recommendation and glad it’s working well for you . I’ve written down a note about adding more documentation for working with charts and I’ll run it by the team tomorrow to get it into the pipeline. I hope you’re having a great weekend!
Basically, almost every* Streamlit element outputs an object that can be used to modify itself.
*(exceptions: widgets, st.write, st.spinner)
For example, when you do el = st.image(img) you can just call other st methods on el to replace it with another element:
# Draw an image element.
el = st.image(img)
time.sleep(0.5)
# Replace the image with some text.
el.text('hi')
time.sleep(0.5)
# Replace the text with a progress bar.
el.progress(50)
# and so on.
There are a few exceptions to the pattern above (most prominently, st.write()!), but in general this should work.
Another trick is to use el = st.empty() to insert a placeholder element that you’ll fill later by calling el.something_else()!
Ok, so going back to your script, here’s a modified version that works on my end:
import streamlit as st
import numpy as np
import time
def get_frame():
return np.random.randint(0, 255, size=(10,10))
my_image = st.image(get_frame(), caption='Random image', width=600)
while True:
time.sleep(0.1)
my_image.image(get_frame(), caption='Random image', width=600)
Dear @namitjuneja. Welcome to the community. I’m really sorry you’ve had this problem.
I suspect that the buy you’re seeing is due to a configuration we haven’t seen before.
To help us solve this for you, could you please submit a bug on Github including the exact code you’re running? An official bug report helps us because the form a bunch of useful questions about your configuration.
That’s definitely something we’ve been thinking about over here. We’d like to be able to support all sorts of data operations, like prepend, pop, update, etc. But first we need to come up with the proper “Streamlity” API for that
Here is a thought on how such an API could work — I’d love to hear your thoughts on it:
(Note: This is just an idea! Not saying we’ll definitely implement it this way)
First, we’d deprecate st.add_rows. That API is a bit weird anyway. Only some elements support it, but all elements have that method. Also, if we wanted to add more methods (like prepend_rows, remove_rows, etc) we’d be polluting the st namespace quite a bit.
Second, we’d add a new st.Data object that wraps dataframes/NdArrays/lists/etc, and which you could mutate directly in order to update your app:
data = st.Data(my_dataframe)
st.line_chart(data)
# Append some rows
data += more_rows
# Or maybe data.append(more_rows)
# This would replace add_rows()
# Remove 10 rows from the head
del data[:10]
# Or maybe data.remove(0, 10)
# Remove 10 rows from the tail
del data[-10:]
# Or maybe data.remove(-10, 0)
# Replace row 50
data[50] = new_row
# Or maybe data.set(50, new_rows)
All the data operations above would happen immediately in your app! So instead of calling .add_rows() on an element, you’d just operate on the Data object directly and things would magically happen behind the scenes. You could even have multiple charts depend on the same data!
You could still pass dataframes directly into st.line_chart, by the way! That would work, but you just wouldn’t be able to later modify your chart by mutating the data.
Anyway, this is just an idea we’re toying with. It’s still in early design phase, so it’s not in Github yet. But I’m creating a feature request for additional data mutation methods here, which we’ll update when we have a better idea what to build.
In the meantime, you can always mutate your original dataset and rerun the chart command to update it on the screen. This works, but it’s a bit wasteful since you’d be sending the entire data to the app every time.
I haven’t tried myself, since I don’t have the whole script, but My guess is that the original snippet had a mistake. In order to redraw, we need to operate on the handle of an existing Streamlit object.
If you still have the problem, I would be happy to debug the whole script for you. Just paste here the final version you have.
Thanks for stopping by! We use cookies to help us understand how you interact with our website.
By clicking “Accept all”, you consent to our use of cookies. For more information, please see our privacy policy.
Cookie settings
Strictly necessary cookies
These cookies are necessary for the website to function and cannot be switched off. They are usually only set in response to actions made by you which amount to a request for services, such as setting your privacy preferences, logging in or filling in forms.
Performance cookies
These cookies allow us to count visits and traffic sources so we can measure and improve the performance of our site. They help us understand how visitors move around the site and which pages are most frequently visited.
Functional cookies
These cookies are used to record your choices and settings, maintain your preferences over time and recognize you when you return to our website. These cookies help us to personalize our content for you and remember your preferences.
Targeting cookies
These cookies may be deployed to our site by our advertising partners to build a profile of your interest and provide you with content that is relevant to you, including showing you relevant ads on other websites.