Save an editable table

Hey there !

I have an editable data frame that I want the user to filter (base on a few columns) and edit rows . after editing the data I want to save it and use it for further calculation .

The problem is every time a user change the table and then filter by other filter and come back the changes he made dose’nt save.

how can I save it ?

after reading and trying some things this is my code :

I keep get the message that st.session_state has no key “df” although I initialled it !


def load_and_edit_dataframe(budget_data,app_name):

    query_comp = budget_data.replace("@app_name@",app_name)
    df = extract_data(query_comp)
    df = pd.DataFrame(df)
    df = pd.DataFrame(df, columns=['app_name','target_month','platform','channel_type','channel','daily_target','monthly_target'])
    return df



App = ["popslot", "mgms", "bingo", "bgpoker", "myvegas", "konami", "tetris", "tetris3", "brn_solitaire", "brn_spider",
       "tetris_blocks"]

# Create a Streamlit app
st.title("Budget Data Editor")

st.sidebar.header('Filters')
selected_app = st.sidebar.selectbox('App name:',options=App)

budget = load_and_edit_dataframe(budget_data,selected_app)

sorted_target_month = sorted(budget.target_month.unique())
selected_target_month = st.sidebar.selectbox('Month',sorted_target_month)
selected_target_month = [selected_target_month]

sorted_platform = sorted(budget.platform.unique())
selected_platform = st.sidebar.multiselect('Platform',sorted_platform,default=sorted_platform)

sorted_channel_type = sorted(budget.channel_type.unique())
selected_channel_type = st.sidebar.multiselect('Channel_type',sorted_channel_type,default=sorted_channel_type)

sorted_channel = sorted(budget.channel.unique())
selected_channel = st.sidebar.multiselect('Channel',sorted_channel,default=sorted_channel)

selected_df = budget[(budget.target_month.isin(selected_target_month)) &
                     (budget.platform.isin(selected_platform)) &
                     (budget.channel_type.isin(selected_channel_type)) &
                     (budget.channel.isin(selected_channel))]

st.header('Edited data:')

# st.session_state.df = selected_df


column_config = {
         'app_name' : st.column_config.SelectboxColumn('App name', options=selected_df.app_name.unique() ,required=True),
         'target_month' : st.column_config.SelectboxColumn('Target month', options=selected_df.target_month.unique(),required=True),
         'platform' : st.column_config.SelectboxColumn('Platform', options=selected_df.platform.unique(),required=True),
         'channel_type' : st.column_config.SelectboxColumn('Channel type', options=selected_df.channel_type.unique(),required=True),
         'channel' : st.column_config.SelectboxColumn('Channel', options=selected_df.channel.unique(),required=True),
         'daily_target' : st.column_config.NumberColumn('Daily target',min_value=0, format="$%d"),
         'monthly_target' : st.column_config.NumberColumn('Monthly target',min_value=0, format="$%d"),

 }



def merge_df(new_df: Union[pd.DataFrame, None] = None):
    if new_df is not None:
        if new_df.equals(st.session_state["df"]):
            return
        st.session_state["df"] = new_df
    st.experimental_rerun()

    if "df" not in st.session_state:
        st.session_state["df"] = selected_df
        merge_df()


editable_df =st.data_editor(st.session_state["df"], key='data_editor', column_config=column_config, num_rows="dynamic", hide_index=True)

merge_df(editable_df)

Thanks a lot !!!

Hi @Yuval_Shemer. Thanks for the question. To help the community read your post, please can you format your code? If you surround your code block with triple backticks or use the code icon in the toolbar you can make your code readable:

like this

1 Like

Actually the code you posted raises NameError: name 'budget_data' is not defined. You must be running some other code.

Anyway,

I keep get the message that st.session_state has no key “df” although I initialled it !

No, you didn’t. You are trying to get the value before the initialization happens.

The budget_data is a data frame I upload from my data base I didn’t add this part …

So should I initilaize it before the function like that :

st.session_state.df = selected_df

It’s still raise the same error :neutral_face:

It doesn’t raise any exceptions for me if I do that. You must be doing something different.

Maybe I initilaized it in the wrong place ? this is my whole code :

I still get the same error of the initialization




App = ["popslot", "mgms", "bingo", "bgpoker", "myvegas", "konami", "tetris", "tetris3", "brn_solitaire", "brn_spider",
       "tetris_blocks"]

# Create a Streamlit app
st.title("Budget Data Editor")

st.sidebar.header('Filters')
selected_app = st.sidebar.selectbox('App name:',options=App)

budget = load_and_edit_dataframe(budget_data,selected_app)

sorted_target_month = sorted(budget.target_month.unique())
selected_target_month = st.sidebar.selectbox('Month',sorted_target_month)
selected_target_month = [selected_target_month]

sorted_platform = sorted(budget.platform.unique())
selected_platform = st.sidebar.multiselect('Platform',sorted_platform,default=sorted_platform)

sorted_channel_type = sorted(budget.channel_type.unique())
selected_channel_type = st.sidebar.multiselect('Channel_type',sorted_channel_type,default=sorted_channel_type)

sorted_channel = sorted(budget.channel.unique())
selected_channel = st.sidebar.multiselect('Channel',sorted_channel,default=sorted_channel)

selected_df = budget[(budget.target_month.isin(selected_target_month)) &
                     (budget.platform.isin(selected_platform)) &
                     (budget.channel_type.isin(selected_channel_type)) &
                     (budget.channel.isin(selected_channel))]

st.header('Edited data:')

st.session_state.df = selected_df


column_config = {
         'app_name' : st.column_config.SelectboxColumn('App name', options=selected_df.app_name.unique() ,required=True),
         'target_month' : st.column_config.SelectboxColumn('Target month', options=selected_df.target_month.unique(),required=True),
         'platform' : st.column_config.SelectboxColumn('Platform', options=selected_df.platform.unique(),required=True),
         'channel_type' : st.column_config.SelectboxColumn('Channel type', options=selected_df.channel_type.unique(),required=True),
         'channel' : st.column_config.SelectboxColumn('Channel', options=selected_df.channel.unique(),required=True),
         'daily_target' : st.column_config.NumberColumn('Daily target',min_value=0, format="$%d"),
         'monthly_target' : st.column_config.NumberColumn('Monthly target',min_value=0, format="$%d"),

 }


def merge_df(new_df: Union[pd.DataFrame, None] = None):
    if new_df is not None:
        if new_df.equals(st.session_state["df"]):
            return
        st.session_state["df"] = new_df
    st.experimental_rerun()

    if "df" not in st.session_state:
        st.session_state["df"] = selected_df
        merge_df()


editable_df =st.data_editor(st.session_state["df"], key='data_editor', column_config=column_config, num_rows="dynamic", hide_index=True)

merge_df(editable_df)

After defining the undefined names, your code doesn’t raise any errors for me. Note that those names will be defined in a different way for you and that may cause different behavior.