I’m working on an app where I’m allowing the user to filter and sort a dataframe and select multiple rows. The sorting will happen regularly so the native row selection on st.dataframe
is not going to be useful, since it wipes out the selections after any sort on columns.
I came up with a solution to add a “Select” column to an st.data_editor
which preserves the selection on sorts, but still wipes them out when the dataframe is filtered.
@arnaud I stumbled upon this post where you had proposed the same exact solution to allow row selection on an editable dataframe:
Is there a way to add filters in a way that it preserves previous selections?
I’ve tried using session_state to “save” the selection and then apply those to the filtered dataframe, but it acts wonky and always lags by one interaction with the dataframe. Same thing with using an external file to save the state of the dataframe.
I also tried using a submit form to again “save” the selected rows and apply them to the filtered data but didn’t have any success there either.
I’ve updated the original code posted in the link above with a simple filter
import streamlit as st
import numpy as np
import pandas as pd
df = pd.DataFrame(
{
"Animal": ["Lion", "Elephant", "Giraffe", "Monkey", "Zebra"],
"Habitat": ["Savanna", "Forest", "Savanna", "Forest", "Savanna"],
"Lifespan (years)": [15, 60, 25, 20, 25],
"Average weight (kg)": [190, 5000, 800, 10, 350],
}
)
# I'm defining and applying a simple filter here as an example
life_span_range = st.sidebar.slider("Select Lifespan range", 15, 60, (15, 60))
df = df[df["Lifespan (years)"].between(*life_span_range)]
def dataframe_with_selections(df: pd.DataFrame, init_value: bool = False) -> pd.DataFrame:
df_with_selections = df.copy()
df_with_selections.insert(0, "Select", init_value)
# Get dataframe row-selections from user with st.data_editor
edited_df = st.data_editor(
df_with_selections,
hide_index=True,
column_config={"Select": st.column_config.CheckboxColumn(required=True)},
disabled=df.columns,
)
# Filter the dataframe using the temporary column, then drop the column
selected_rows = edited_df[edited_df.Select]
return selected_rows.drop('Select', axis=1)
selection = dataframe_with_selections(df)
st.write("Your selection:")
st.write(selection)
Any help or insights would be greatly appreciated!