Automatically updating plots using data streams

I recently found this very interesting article about real time dashboard and thought that this would be also a nice addition to Streamlit. It’s core functionality, the PeriodicDataFrame, regularly updates the data via an external asyncio event loop. From the docs:

A PeriodicDataFrame uses Python’s asyncio event loop (used as part of Tornado in Jupyter and other interactive frameworks) to call a user-provided function at a regular interval, collecting the results and making them available for later processing.

If I understood correctly Streamlit is also build around tornado so this could also be accomplished, right? Here are my first baby steps:

In Jupyter Notebooks

The streamz functionality and holoviews already work together perfectly, creating bokeh plots as a result, which are automatically updated in jupyter notebooks. Here is the code:

import random

import holoviews as hv
import numpy as np
import pandas as pd
import streamlit as st

from streamz.dataframe import PeriodicDataFrame

pd.options.plotting.backend = 'hvplot'

def random_data(**kwargs):
    return pd.DataFrame({
            'data': [random.randint(0, 10) for _ in range(10)]

df = PeriodicDataFrame(random_data, interval='1000ms')

fig = df.plot.hist(bins=np.linspace(-0.5, 10.5, 12))

# st.bokeh_chart(hv.render(fig, backend='bokeh'))


You can see the result here:


In Streamlit Dashboards

For streamlit, I tried the exact same code but commenting in the st.bokeh_chart part, of course :slight_smile:. Here is the result:

I know its a png, but trust me, nothing was updating here :smiley:.

Hint: If you want to try it yourself, make sure to downgrade bokeh to version 2.2.2 as described here, otherwise the script will fail.

Final thoughts

Thinking of event streaming platforms like Apache Kafka this could be a big deal. Do you have any idea on how we could accomplish this automatically updating of plots behavior in Streamlit?

Hi @tschmelzer, welcome to the Streamlit community!

You’re right, this would be an interesting functionality. Not sure where someone might get started with this, but it seems like it would be possible.