import streamlit as st
from palmerpenguins import load_penguins
import plotly.express as px
import time
= load_penguins()
penguins
= st.columns(2)
app_column_1, app_column_2
= ['bill_length_mm', 'bill_depth_mm',
axis_options 'flipper_length_mm', 'body_mass_g']
with app_column_1:
3)
time.sleep(= st.selectbox("Select a penguin species to filter by", ["Adelie", "Gentoo", "Chinstrap"])
species = penguins[penguins['species'] == species]
filtered_df_species 'sex'].value_counts(), y='count'))
st.plotly_chart(px.bar(filtered_df_species[
with app_column_2:
3)
time.sleep(= 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 y 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)
33 Partial Reruns (fragments)
Partial reruns are a faily new feature in Streamlit that allow you to break out of the traditional top-to-bottom rerun pattern of a Streamlit app.
Let’s imagine that we have an app with two visualisations in - a bar chart on the left, and a scatterplot on the right.
We have two separate sets of filters - one that only affects the left visual, and one that affects the right.
In a standard app, the whole thing would rerun even though only one of the visuals theoretically needs to be updated. Let’s take a look at the app as we would have generally written it.
A short delay has been added in to make it clearer when the app is updating. What you will notice is that when any item is changed in the dropdown menu, the whole app fades out as all of the plots are recalculated, even though this is unnecessary as the right drop-downs don’t affect the left plot, and vice-versa.
33.1 The Partial Rerun Decorator
Now let’s rewrite this using the fragment code.
import streamlit as st
from palmerpenguins import load_penguins
import plotly.express as px
import time
= load_penguins()
penguins
= st.columns(2)
app_column_1, app_column_2
= ['bill_length_mm', 'bill_depth_mm',
axis_options 'flipper_length_mm', 'body_mass_g']
1@st.fragment()
2def penguin_barchart():
3)
time.sleep(= st.selectbox("Select a penguin species to filter by", ["Adelie", "Gentoo", "Chinstrap"])
species = penguins[penguins['species'] == species]
filtered_df_species 'sex'].value_counts(), y='count'))
st.plotly_chart(px.bar(filtered_df_species[
3@st.fragment()
def penguin_scatterplot():
3)
time.sleep(= 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 y 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)
with app_column_1:
4
penguin_barchart()
with app_column_2:
5 penguin_scatterplot()
- 1
-
We use the
@st.fragment()
decorator on its own line - 2
-
Instead of just creating the inputs and outputs straight in the app, we need to wrap them in a function. This function doesn’t need to return anything, and we can call it whatever we like. Note that there is no blank line between the
@st.fragment()
decorator and the function definition. Here, we’ve counted the select dropdown for species, the pandas dataframe filter action, and the creation of the barplot figure as being a single thing we want to rerun when any element within those three changes in a way that would trigger a rerun usually. - 3
- We then repeat this for our next function.
- 4
-
Using the
with
notation with the first column we created, we then call our first function. - 5
- We then repeat this for the second column and second function.
As the fragments feature is so new as of writing this book, it has not yet been integrated into the library we use for displaying the example apps.
Instead, you can view the output of this code in the embedded webpage below.
Notice that now when we change the parameters in the drop-down select boxes, only half of the app fades out - indicating that only half of the app is updating at a time; each half of the page can now act independently of the other.
Click here to open the example app if it does not load in the box below