Session State with st.data_editor

Summary

Hi, everyone! How can I use st.date_editor with session state? In this project, the user can edit some data and the run an analysis. The problem is that apparentely there is no session state when it comes to st.date_editor. I’ve seen in a forum a solution which basically saves the edited df to a static df with “on_change” method, but I couldnt reproduce it.

Steps to reproduce

Code snippet:

st.session_state['id_dados_gerais'] = (st.session_state['df_dados_gerais_unidades'].loc[st.session_state['df_dados_gerais_unidades']['Unidade'] == st.session_state['cliente']])
        
st.data_editor(st.session_state['id_dados_gerais'], hide_index=True, column_order=('Distribuidora', 'Classe de Tensão', 'Modalidade Tarifária', 'Demanda Contratada Ponta', 'Demanda Contratada Fora Ponta', 'Desconto', 'CDE Covid', 'CDE Escassez Hídrica', 'Comunhão'), disabled=('Distribuidora', 'Classe de Tensão'))

So basically the user edits some data in the st.session_state[‘id_dados_gerais’] and then the data provided would be used to do an analysis.

Expected behavior:

Use the edited data to run the analysis

Actual behavior:

The analysis is made with the original data.

Thank you in advance!

Hi @heitormarcal

The following Docs page provides example code snippets to save edits to session state

The relevant code snippet mentioned in the above Docs page:

st.data_editor(df, key="data_editor") # 👈 Set a key
st.write("Here's the session state:")
st.write(st.session_state["data_editor"]) # 👈 Access the edited data

Is there any way to store the complete dataframe in the session state, not only the changes?

I have a use case in a mulitpage application, where I need to do changes on a dataframe on one page, which is then used on another page. This does not seem to be straight forward with the current implementation, where only the changes are stored in session state.

One way would be to store the data_editor initial dataframe itself in the session state, and update it when the output changes, as in the code below. This does not work however when updating the data multiple times.

if "initial_df" not in st.session_state:
    st.session_state["initial_df"] = pd.DataFrame(
        [
            {"color": "red", "rating": 4},
            {"color": "green", "rating": 5},
            {"color": "blue", "rating": 3},
        ]
    )

updated_df = st.data_editor(st.session_state["initial_df"], num_rows="dynamic")

if not st.session_state["initial_df"].equals(updated_df):
    st.session_state["initial_df"] = updated_df.copy()

Hey, dagfnaer!

Have you considered defining a session state to your ‘updated_df’ ?

I’m doing it in my projects and it works! It would look like this:

st.session_state["updated_df "] = st.data_editor(st.session_state[“initial_df”], num_rows=“dynamic”)

You can now access the full edited df through st.session_state["updated_df "]

Thanks for the reply @heitormarcal. Saving updated_df in the session_state does not really solve the problem, which is that the every second edited value in the data_editor disappears. When this happens, it seems like the data_editor widget is refreshed with the previous initial_df.

It seems that it’s happening because of this statement:

 if not st.session_state["initial_df"].equals(updated_df):
    st.session_state["initial_df"] = updated_df.copy()

Instead of initializing like that, try:

if 'initial_df' not in st.session_state:
    st.session_state['initial_df'] = ''
if 'updated_df ' not in st.session_state:
    st.session_state['updated_df '] = ''

Then you can create your df:

st.session_state["initial_df"] = pd.DataFrame(
        [
            {"color": "red", "rating": 4},
            {"color": "green", "rating": 5},
            {"color": "blue", "rating": 3},
        ]
    )

and edit it:


st.session_state['updated_df '] = st.data_editor(st.session_state["initial_df"], num_rows="dynamic")

Then, if you want to access your edited ‘initial_df’, you can access st.session_state['updated_df ']

Your approach works for a single-page application. However, I am developing a multipage application, meaning that the data_editor is re-initialized with st.session_state["initial_df"] whenever the user is changing from another page to the page with the data_editor.

With the current implementation, I need to update the st.session_state["initial_df"] with the latest updates. As you point out, this is what causes the edited data to disappear, but I don’t really understand why. A workaround would be to only update it when leaving the page with the data_editor, but I have not found a way to do this.

hi!

Well, the session state is supposed to persist in multipage applications (Session State - Streamlit Docs)

Not that I’m a Streamlit pro, but I’d give a last chance trying to help you asking if you’re using the latest version of Strealit.

I’m using version 1.28.1 and the session_state does persist when changing pages, which means that I can access an edited df from page “A” on page “B”.

However, and it’s important to mention, everytime I change from one page to another and then go back to the previous, it seems that it resets the edited df, indeed… if that was your point since the beggining, sorry for the confusion! And in case you find a solution, please share!

@dataprofessor, good morning! Any comment on this issue?
thanks in advance!

Yes, exactly. The problem is persisting state between page changes. From my understanding the data_editor widget is a bit different from other widgets, making this challenging.

A solution like the one described here would work if there was a way to do a similar on_change callback when switching page in a multipage app, but as far as I know this is not possible.