Dataframes in st.data_editor vs. st.dataframe

Summary

Dataframe in st.session_state that is being edited in an st.data_editor widget is not being updated from other widget actions (in this case, a file_uploader widget).

Steps to reproduce

Code snippet:

import streamlit as st
import pandas as pd

if 'df' not in st.session_state: 
    st.session_state['df'] =  pd.DataFrame({'Exclude': [False, False, False]}) 

st.write('Session state dataframe:')
st.dataframe(st.session_state['df'])

file = st.file_uploader('Exclude File')

if file is not None:
    df_load = pd.read_csv(file)
    st.write('Loaded dataframe:')
    st.dataframe(df_load) # not really being used.  Actual app uses it.
    st.session_state['df'].loc[0, 'Exclude'] = True
    st.dataframe(st.session_state['df'])

st.write('Session state dataframe after load:')
st.dataframe(st.session_state['df'])

st.write('Session state dataframe in data editor:')
st.data_editor(st.session_state['df'])

Using the file_uploader widget, a CSV file with the contents below is loaded.

Exclude
True

In the Streamlit app, the file contents are read and used to set the Exclude column to True in the dataframe’s first row (file is not used here in this example, but it is in the actual app).

After loading the CSV file for the first time, the intended behavior is observed. The dataframe in the st.data_editor correctly shows its first row of the Exclude column as checked.

Then, if I check rows 2 and 3 of the exclude column in st.data_editor (I’m aware that this is not changing the dataframe in st.session_state) and reload the CSV file, the first row does not become checked anymore.

Expected behavior:

When loading the file, the first row of the dataframe in st.data_editor should be checked.

Actual behavior:

The first row of the dataframe’s Exclude column should always be checked upon loading the file. The current behavior may well be the intended/expected behavior, but I want to confirm.
output

Debug info

  • Streamlit version: 1.23.1
  • Python version: 3.11.3
  • Using Conda? PipEnv? PyEnv? Pex? No
  • OS version: macOS Ventura 13.4
  • Browser version: Chrome Version 114.0.5735.133 (Official Build) (arm64)

Additional information

Uploaded a GIF to show the behavior.

Here’s what’s happening:

  1. Your script has the initial (all False) dataframe, saved in session state.
  2. You load a file and the page reruns.
  3. At the beginning of the rerun, your dataframe in session state is not yet updated.
  4. When the rerun gets to the file uploader, you execute a line to modify the dataframe saved in session state. It now has the first row as True.
  5. You make edits with the data editor, setting the first row back to False and the other rows to True.

At this point, your data editor has an underlying dataframe [T, F, F] with edits setting it to [F, T, T].

  1. You remove your file. You code no longer executes the line setting the first row to True, but it doesn’t matter because that change is already committed to session state.
  2. You reupload the file and again the code is executed to set the first row to True. However, it is already True from the last time it was edited (directly in session state).
  3. The data editor sees no change to the underlying dataframe and so does not reset.

If you did change the underlying dataframe passed to the data editor, all edits it was “remembering” would be discarded, by the way.

1 Like

Hi, I think I have a similar question. I’m not seeing the st.data_editor getting refreshed. I have a True/False dataframe I want users to interact with (there’s a commit button that’s working to save back to a database) and I’m trying to add an “Undo” button that discards the change. I’ve tried multiple things and I can’t seem to get the editable dataframe to refresh.

Right now, I keep the state of the original dataframe and the editable dataframe in separate session state variables. I thought upon clicking the button, I could make whatever changes I’ve edited reverse on the editable dataframe by reassigning the editable one from the original one.

The behavior I see is that I can click all three Falses, and the checkboxes are now True. When I click undo, I would expect the underlying edit_df to change and show all False - however, they are all still showing True and have not be refreshed.

Is there a way to force the editable dataframe in data_editor to show new values based on some process programmatically reprocessing the underlying dataframe?