Python Streamlit - filter pandas dataframe without rerun entire script

Viewed 2421

I have the following code:

import streamlit as st
import pandas as pd

#define data
d = {'id': ['a', 'b', 'c'], 'data': [3, 4,6]}
df = pd.DataFrame(data=d)

#create sidebar input
with st.sidebar.form("my_form"):
    a = st.slider('sidebar for testing', 5, 10, 9)
    calculate = st.form_submit_button('Calculate') 
 

if calculate:
    df['result'] = df['data'] + a 
    st.write(df)
    #no issues up to this point. When I move the slider in 10 the output in 16 stays on the web page

    ########debug############
    # I am trying to select an 'id' from the dropdown and use that to filter df, but when I select a value from the dropdown, 
    # the script runs again and the output disappears
    filter = st.selectbox('filter data', df['id'].unique())
    st.write(df[df['id'] == filter])

I would like to filter the Pandas dataframe using a drop down menu to select the id I am interested in, but when I use the drop down the code reruns.

Any idea how I can solve this?

PS I also tried enclosing the entire computation in a function and adding the @st.cache decorator, but without success. I would appreciate it if anyone could show me how it’s done.

2 Answers

I was able to get this behavior by not using the submit button. Streamlit reruns the script from top to bottom any time there's user input, so the form submit resets as well.

d = {'id': ['a', 'b', 'c'], 'data': [3, 4, 6]}
df = pd.DataFrame(data=d)

a = st.slider('sidebar for testing', 5, 10, 9)

df['result'] = df['data'] + a
st.write(df)

# Now this will show the filtered row in the dataframe as you change the inputs
filter = st.selectbox('filter data', df['id'].unique())
st.write(df[df['id'] == filter])

For more complicated workflows, I'd refactor this and cache data that gets loaded in, but for filtering your dataframe, this should work.

Streamlit always re-runs the code on each user-submission. You can however solve this with st.session_state, which allows sharing states between reruns. Its api is a lot like a standard python dictionary.

Here is your example with st.session_state:

import streamlit as st
import pandas as pd

#define data
d = {'id': ['a', 'b', 'c'], 'data': [3, 4,6]}
df = pd.DataFrame(data=d)


#create sidebar input
with st.sidebar.form("my_form"):
    a = st.slider('sidebar for testing', 5, 10, 9)
    calculate = st.form_submit_button('Calculate')

# Initialization
if 'button_pressed' not in st.session_state:
    st.session_state['button_pressed'] = False

# Changes if calculated button is pressed  
if calculate:
    st.session_state['button_pressed'] = True

# Conditional on session_state instead
if st.session_state['button_pressed']:
    df['result'] = df['data'] + a
    st.write(df)
    #no issues up to this point. When I move the slider in 10 the output in 16 stays on the web page

    ########debug############
    # I am trying to select an 'id' from the dropdown and use that to filter df, but when I select a value from the dropdown,
    # the script runs again and the output disappears
    filter = st.selectbox('filter data', df['id'].unique())
    st.write(df[df['id'] == filter])
Related