Learn how to make your pyplot charts interactive in a few simple steps
Matplotlib is one of the most popular charting libraries in Python. Itās also a popular way to add charts to your Streamlit apps. Just use st.pyplot
!
But Matplotlib charts are static images. No zooming or moving the chart around.
In this post, I'll show you how to make them interactive:
1. Simple example:
- Step 1. Create a basic Matplotlib chart
- Step 2. Make the chart interactive
2. Advanced example:
- Step 1. Render the graph statically
- Step 2. Make the graph interactive with mpld3
- Step 3. Add tooltips for even more interactivity
TLDR? Use mpld3 and render pyplots with Streamlitās built-in st.pyplot
command. With a few lines of code, you can add panning, zooming, resetting, and rendering!
1. Simple example
Step 1. Create a basic Matplotlib chart
First, create a basic Matplotlib chart and add it to your Streamlit app (youāll add interactivity later).
Here is what the code will look like:
import streamlit as st
import matplotlib.pyplot as plt
#create your figure and get the figure object returned
fig = plt.figure()
plt.plot([1, 2, 3, 4, 5])
st.pyplot(fig)
And hereās what your app should look like now:
Step 2. Make the chart interactive
Making this chart interactive is super simple.
Use the fantastic mpld3 library. Itāll convert the Matplotlib figure (fig
) into an interactive Javascript representation and return it as HTML. Embed this HTML snippet in your app via Streamlitās custom component API:
import matplotlib.pyplot as plt
import matplotlib.pyplot as mpld3
import streamlit.components.v1 as components
#create your figure and get the figure object returned
fig = plt.figure()
plt.plot([1, 2, 3, 4, 5])
fig_html = mpld3.fig_to_html(fig)
components.html(fig_html, height=600)
Now your users can pan, zoom, reset, and explore the details of your chart! š
Want to explore it yourself? See the app deployed live here.
For more mpld3ās plugins, check out mpld3ās website and documentation.
2. Advanced example
Step 1. Render the graph statically
Start out by statically rendering the graph:
# Imports for all of the code
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import mpld3
import streamlit as st
from mpld3 import plugins
def f(t):
return np.exp(-t) * np.cos(2*np.pi*t)
t1 = np.arange(0.0, 5.0, 0.1)
t2 = np.arange(0.0, 5.0, 0.02)
# How to set the graph size
two_subplot_fig = plt.figure(figsize=(6,6))
plt.subplot(211)
plt.plot(t1, f(t1), color='tab:blue', marker=',')
plt.plot(t2, f(t2), color='black', marker='.')
plt.subplot(212)
plt.plot(t2, np.cos(2*np.pi*t2), color='tab:orange', linestyle='--', marker='.')
st.pyplot(two_subplot_fig)
This code will make something like this:
You might be thinking, āWhy are we adding markers? It doesnāt look beautiful.ā Iāll explain why below!
Step 2. Make the graph interactive with mpld3
Make the static graph interactive with mpld3:
# Replace st.pyplot(two_subplot_fig) with this code below!
fig_html = mpld3.fig_to_html(two_subplot_fig)
components.html(fig_html, height=600)
Here is what itāll look like with panning, zooming, and resetting:
Add tooltips to see X and Y coordinates for even more interactivity (itās why weāve added markers).
Here is what the code will look like:
# CODE TO ADD
# Define some CSS to control our custom labels
css = """
table
{
border-collapse: collapse;
}
th
{
color: #ffffff;
background-color: #000000;
}
td
{
background-color: #cccccc;
}
table, th, td
{
font-family:Arial, Helvetica, sans-serif;
border: 1px solid black;
text-align: right;
}
"""
for axes in two_subplot_fig.axes:
for line in axes.get_lines():
# get the x and y coords
xy_data = line.get_xydata()
labels = []
for x, y in xy_data:
# Create a label for each point with the x and y coords
html_label = f'<table border="1" class="dataframe"> <thead> <tr style="text-align: right;"> </thead> <tbody> <tr> <th>x</th> <td>{x}</td> </tr> <tr> <th>y</th> <td>{y}</td> </tr> </tbody> </table>'
labels.append(html_label)
# Create the tooltip with the labels (x and y coords) and attach it to each line with the css specified
tooltip = plugins.PointHTMLTooltip(line, labels, css=css)
# Since this is a separate plugin, you have to connect it
plugins.connect(two_subplot_fig, tooltip)
You can adjust HTML, CSS, or anything you want. And if you want to interact with the graph or look at the code, check it out here!
Note: mpld3 limitations
Before I wrap this up, I wanted to note the limitations to mpld3:
- Complex charts sometimes donāt render properly.
- Dark mode isnāt supported.
- 3D charts donāt render properly.
- You need markers for tooltips.
- Some markers donāt work (examples: none or ā+ā).
Wrapping up
Thank you for reading this post! Iād love to know if you found this useful. Your feedback means a LOT. If you have any questions, please leave them in the comments below and check out the forum to see what our vibrant community is creating.
Happy Streamlit-ing! š
This is a companion discussion topic for the original entry at https://blog.streamlit.io/make-your-st-pyplot-interactive/