[Python] Streamlit data_editor won't update data

Discussão em 'Python' iniciado por Stack, Julho 8, 2025.

  1. Stack

    Stack Membro Participativo

    I am trying to have a data_editor in streamlit that can handle automatic changes from users. The idea, is that user will update a column value and automatically the change will be displayed triggering a calculation within the table. In my example, it should days to expire for a financial option. Pretty much like excel. But I am stuck with the fact that, it will always revert to the previous and it needs "two clicks".

    Here is the code I have (with a lot of chatpt too) At the moment I have creating the edited data frame, because it is failing to update the same data_editor. Ideally, the changes you see on the second data frame, I would like to appear in the input one.

    Can anyone helpout?

    In the code below, is where the problem is, user's input is not registered

    import streamlit as st
    import pandas as pd

    contracts = ['Jan25', 'Feb25', 'Mar25','Apr25','May25','Jun25',
    'Jul25', 'Auh25', 'Sep25', 'Oct25', 'Nov25', 'Dec25']
    options_type = ['Call', 'Put']

    # Only initialize once
    if "editor_df" not in st.session_state:
    st.session_state["editor_df"] = pd.DataFrame({
    "Is Long": [True],
    "Call/Put": [options_type[0]],
    "Contract": [contracts[0]],
    "Strike": [35.0]
    })

    # Show editor and get edited DataFrame
    edited_df = st.data_editor(
    st.session_state["editor_df"],
    key="editor",
    column_config={
    "Is Long": st.column_config.CheckboxColumn(default=True),
    "Call/Put": st.column_config.SelectboxColumn(options=options_type),
    "Contract": st.column_config.SelectboxColumn(options=contracts),
    "Strike": st.column_config.NumberColumn(default=35.0),
    },
    num_rows="dynamic"
    )

    # Compare before assigning
    if not edited_df.equals(st.session_state["editor_df"]):
    st.session_state["editor_df"] = edited_df.copy()


    The below code is the workaround I have. Populate two tables. The first is the input and the second calculates the extra field.

    import streamlit as st
    import pandas as pd
    import datetime

    # Define contracts and expiries
    contracts = ['Jan25', 'Feb25', 'Mar25', 'Apr25', 'May25', 'Jun25',
    'Jul25', 'Aug25', 'Sep25', 'Oct25', 'Nov25', 'Dec25']
    options_type = ['Call', 'Put']

    expiries = {
    'Jan25': datetime.datetime(2024, 12, 27),
    'Feb25': datetime.datetime(2025, 1, 29),
    'Mar25': datetime.datetime(2025, 2, 26),
    'Apr25': datetime.datetime(2025, 3, 27),
    'May25': datetime.datetime(2025, 4, 28),
    'Jun25': datetime.datetime(2025, 5, 28),
    'Jul25': datetime.datetime(2025, 6, 26),
    'Aug25': datetime.datetime(2025, 7, 29),
    'Sep25': datetime.datetime(2025, 8, 27),
    'Oct25': datetime.datetime(2025, 9, 26),
    'Nov25': datetime.datetime(2025, 10, 29),
    'Dec25': datetime.datetime(2025, 11, 27)
    }

    # Initialize session state
    if "editor_df" not in st.session_state:
    st.session_state.editor_df = pd.DataFrame({
    "Is Long": [True],
    "Call/Put": ["Call"],
    "Contract": ["Jan25"],
    "Strike": [35.0]
    })

    # Show editor first
    edited_df = st.data_editor(
    st.session_state.editor_df,
    key="editor",
    column_config={
    "Is Long": st.column_config.CheckboxColumn(),
    "Call/Put": st.column_config.SelectboxColumn(options=options_type),
    "Contract": st.column_config.SelectboxColumn(options=contracts),
    "Strike": st.column_config.NumberColumn(),
    },
    num_rows="dynamic"
    )

    # Compute days on what user just changed
    def compute_days(df: pd.DataFrame) -> pd.DataFrame:
    now = datetime.datetime.now()

    def get_days(contract):
    expiry = expiries.get(str(contract))
    if not isinstance(expiry, datetime.datetime):
    return 0.0
    delta = expiry - now
    return max(delta.total_seconds() / 86400, 0.0)

    df = df.copy()
    df["Days to expiry"] = df["Contract"].apply(get_days)
    return df

    # Compute on latest edited data
    final_df = compute_days(edited_df)

    # Show full live-updated table
    st.dataframe(final_df)

    Continue reading...

Compartilhe esta Página