import streamlit as st
import pandas as pd
import matplotlib.pyplot as plt
from palmerpenguins import load_penguins
= load_penguins()
penguins
= plt.subplots(figsize=(15,10))
fig, ax =penguins["body_mass_g"], y=penguins["bill_length_mm"])
plt.scatter(x"Penguin Body Mass (g) versus Bill Length (mm)")
plt.title("Body Mass (g)")
ax.set_xlabel("Bill Length (mm)")
ax.set_ylabel(
st.pyplot(fig)
= 'penguins_scatter_method_1.png'
filename
plt.savefig(filename)with open(filename, "rb") as img:
= st.download_button(
btn ="Download image",
label=img,
data=filename,
file_name="image/png"
mime )
19 Downloading Images and Charts
19.0.1 Matplotlib
We can provide two possible ways of downloading the output of a matplotlib plot.
The first involves saving the resulting plot to a file, then serving that file to the user. This is a reliable and simple method that is probably the best to use in most situations - it will generally work even when the file is deployed.
The second involves saving the image to tempory memory, then serving that instead.
import streamlit as st
import pandas as pd
import matplotlib.pyplot as plt
from palmerpenguins import load_penguins
from io import BytesIO
= load_penguins()
penguins
= plt.subplots(figsize=(15,10))
fig, ax =penguins["body_mass_g"], y=penguins["bill_length_mm"])
plt.scatter(x"Penguin Body Mass (g) versus Bill Length (mm)")
plt.title("Body Mass (g)")
ax.set_xlabel("Bill Length (mm)")
ax.set_ylabel(
st.pyplot(fig)
= BytesIO()
img
plt.savefig(img)
= st.download_button(
btn ="Download image",
label=img,
data='penguins_scatter_method_2.png',
file_name="image/png"
mime )
19.0.1.1 Wordcloud Example
The popular wordcloud
package is actually using matplotlib for its plotting!
This means that the same approach works for saving a wordcloud.
Here, we are just showing the approach of saving and then serving the image - both to display it in the app and to offer it up to the end user for download.
import streamlit as st
from wordcloud import WordCloud, STOPWORDS
import string
import matplotlib.pyplot as plt
= set(STOPWORDS)
stopwords
def make_wordcloud(text_input):
= text_input.split()
tokens = str.maketrans('', '', string.punctuation)
punctuation_mapping_table = [token.translate(punctuation_mapping_table)
tokens_stripped_of_punctuation for token in tokens]
= [token.lower() for token in tokens_stripped_of_punctuation]
lower_tokens
= (" ").join(lower_tokens)
joined_string
= WordCloud(width=1800,
wordcloud =1800,
height='white',
background_color=stopwords,
stopwords=20).generate(joined_string)
min_font_size
=(30,40))
plt.figure(figsize# Turn off axes
"off")
plt.axis(# Then use imshow to plot an image (here, our wordcloud)
plt.imshow(wordcloud)# The easiest way to do this today is to save the image and reload it
# This works during local testing but would also work if we deployed this
"wordcloud.png")
plt.savefig(
= """
sample_text Penguins are a group of aquatic flightless birds from the family Spheniscidae of the order Sphenisciformes. They live almost exclusively in the Southern Hemisphere: only one species, the Galápagos penguin, is found north of the Equator. Highly adapted for life in the ocean water, penguins have countershaded dark and white plumage and flippers for swimming. Most penguins feed on krill, fish, squid and other forms of sea life which they catch with their bills and swallow whole while swimming. A penguin has a spiny tongue and powerful jaws to grip slippery prey.
They spend about half of their lives on land and the other half in the sea. The largest living species is the emperor penguin (Aptenodytes forsteri): on average, adults are about 1.1 m (3 ft 7 in) tall and weigh 35 kg (77 lb). The smallest penguin species is the little blue penguin (Eudyptula minor), also known as the fairy penguin, which stands around 30–33 cm (12–13 in) tall and weighs 1.2–1.3 kg (2.6–2.9 lb). Today, larger penguins generally inhabit colder regions, and smaller penguins inhabit regions with temperate or tropical climates. Some prehistoric penguin species were enormous: as tall or heavy as an adult human. There was a great diversity of species in subantarctic regions, and at least one giant species in a region around 2,000 km south of the equator 35 mya, during the Late Eocene, a climate decidedly warmer than today.
"""
= st.text_area(label="Enter your text here", value=sample_text)
your_text
=your_text)
make_wordcloud(text_input
"wordcloud.png")
st.image(
with open("wordcloud.png", "rb") as file:
= st.download_button(
btn ="Click Here to Download Your Word Cloud!",
label=file,
data="my_wordcloud.png",
file_name="image/png",
mime )
19.0.2 Seaborn
Saving the file and then serving this is a good way to work with seaborn as well.
import streamlit as st
from palmerpenguins import load_penguins
import seaborn as sns
= load_penguins()
penguins
= sns.pairplot(penguins, hue="species")
pairplot_fig
"pairplot_sns_penguins.png")
pairplot_fig.figure.savefig(
with open("pairplot_sns_penguins.png", "rb") as file:
= st.download_button(
btn ="Click Here to Download Your Pair Plot!",
label=file,
data="pairplot_penguin_species.png",
file_name="image/png",
mime
)
= sns.boxplot(penguins, x="island", y="bill_length_mm")
boxplot_fig
"boxplot_sns_penguins.png")
boxplot_fig.figure.savefig(
with open("boxplot_sns_penguins.png", "rb") as file:
= st.download_button(
btn ="Click Here to Download Your Box Plot!",
label=file,
data="boxplot_penguin_species.png",
file_name="image/png",
mime )
19.0.3 Plotly
Plotly is a bit different because the plots it produces are interactive - but it is possible to save this too.
The resulting file is completely self-contained and can even be used offline. The file could be emailed or placed on a shared site like sharepoint or google drive and would work - though sometimes it requires the user to download the html file to their own machine for it to display correctly rather than just previewing the underlying html data, depending on the platform.
19.0.3.1 Built-in method for downloading static plots
When using plotly, users can hover over the plot and choose ‘Download plot as a png’.
19.0.3.2 Downloading the interactive plots
import streamlit as st
from palmerpenguins import load_penguins
import plotly.express as px
= load_penguins()
penguins
= ['bill_length_mm', 'bill_depth_mm',
axis_options 'flipper_length_mm', 'body_mass_g']
= st.selectbox("Select the column to use for the x axis", axis_options)
col_1
axis_options.remove(col_1)
= st.selectbox("Select the column to use for the x axis", axis_options)
col_2
= st.selectbox("Select the column to colour the chart by",
color_factor "species", "sex", "island"])
[
= px.scatter(penguins, x=col_1, y=col_2, color=color_factor,
fig =f"Penguins Dataset - {col_1} vs {col_2}, coloured by {color_factor}")
title
st.plotly_chart(fig)
"plotly_chart.html")
fig.write_html(
with open("plotly_chart.html", "rb") as file:
st.download_button(='Download This Plot as an Interactive HTML file',
label=file,
data=f'{col_1}_vs_{col_2}_by_{color_factor}.html',
file_name='text/html'
mime )
We could once again use StringIO
to save the chart html temporarily to memory, then write that to a html file when the user clicks on a download button, as opposed to actually saving the file to a html file on our storage wherever our app is running and then serving that file.
That is slightly more complex with Plotly; you could attempt to adapt the code in the ‘Dash’ download button example here.
https://plotly.com/python/interactive-html-export/#html-export-in-dash