Creating multiple pages to create different different DataFrames

Summary

I’m trying to create a form which will create multiple dataframes, save it and then use those datafames to run a python program.

I have created it but the issue is, when i’m clicking on ‘move to task data’ button which will take the user to another form and let them enter the data, i’m getting below error.

first issue is, I need to click on this button twice for it to work… after clicking it twice i’m getting below error… could someone please help me rectify this issue and let me know what am i doing wrong ?

Steps to reproduce

Code snippet:



import pandas as pd
import streamlit as st


session_state = st.session_state

# Define a function to display the resource data collection page
def resource_data_page():

    

    # Define column names for the empty dataframe
    columns = ["Person_name", "Location", "AAAA", "BBBB", "CCCC", "DDDD", "EEEE", "FFFF"]
    # Create an empty dataframe with the defined columns
    empty_df = pd.DataFrame(columns=columns)
    # Define a list of people to choose from
    people = ["John", "Mary", "Jane", "Mark", "Lucy"]
    # Create an empty session state variable
    session_state = st.session_state


    # Add a button to navigate to the task data collection page
    if st.button("Move to Task Data"):
        st.session_state.page = "Task Data"
        
    # Check if the session state variable is already defined
    if "df" not in session_state:
        # Assign the initial data to the session state variable
        session_state.df = empty_df
        session_state.row = pd.Series(index=columns)

    # Create a selectbox for each column in the current row
    for col in columns:
        # Get unique values from the corresponding column in the resource_data dataframe
        if col == "Person_name":
            values = people
        else:
            values = ["Y", "N"]
        # Create a selectbox for the current column and add the selected value to the current row
        index = values.index(session_state.row[col]) if session_state.row[col] in values else 0

        session_state.row[col] = st.selectbox(col, values, key=col, index=index)

    # Add a button to add a new empty row to the dataframe and clear the values of the selectboxes for the current row
    if st.button("Add Row"):
        session_state.df = session_state.df.append(session_state.row, ignore_index=True)
        session_state.row = pd.Series(index=columns)

        # Save the updated data to the CSV file
        session_state.df.to_csv("data.csv", index=False)

    # Display the resulting dataframe
    st.dataframe(session_state.df)

# Define a function to display the task data collection page
def task_data_page():

    st.write("This is the Task Data page.")

    columns = ["task_name", "completion_time", "resource_required", "n_cases"]

    tasks = ["AAAA", "BBBB", "CCCC", "DDDD", "EEEE", "FFFF"]
    completion_time = [4,8]
    resource_required = [1,2,3,4,5,6]
    n_cases = [0,2]
    empty_df = pd.DataFrame(columns=columns)

    session_state = st.session_state

    # Check if the session state variable is already defined
    if "df" not in session_state:
        # Assign the initial data to the session state variable
        session_state.df = empty_df
        session_state.row = pd.Series(index=columns)

    # Create a selectbox for each column in the current row
    for col in columns:
        # Get unique values from the corresponding column in the resource_data dataframe
        if col == "task_name":
            values = tasks
        elif col== 'completion_time':
            values = completion_time
        elif col== 'resource_required':
            values = resource_required
        else:
            values = [0,2]
        # Create a selectbox for the current column and add the selected value to the current row
        index = values.index(session_state.row[col]) if session_state.row[col] in values else 0

        session_state.row[col] = st.selectbox(col, values, key=col, index=index)

    # Add a button to add a new empty row to the dataframe and clear the values of the selectboxes for the current row
    if st.button("Add Row"):
        session_state.df = session_state.df.append(session_state.row, ignore_index=True)
        session_state.row = pd.Series(index=columns)

    # Add a button to navigate to the task data collection page
    if st.button("Next"):
        st.session_state.page = "Task Data"
    
    # Display the resulting dataframe
    st.dataframe(session_state.df)

    st.button("Back to Resource Data", on_click=resource_data_page)


# Define a dictionary to map page names to their corresponding functions
pages = {
    "Resource Data": resource_data_page,
    "Task Data": task_data_page
}

# Check if the current page is already defined in the session state variable
if "page" not in session_state:
    # Assign the initial page to the session state variable
    session_state.page = "Resource Data"

# Display the current page
pages[session_state.page]()

Expected behavior:

If i click on ‘move to task_data’ button, it should allow me to move to task_data and then allow me to enter my details.

Debug info

  • Streamlit version: latest
  • Python version:latest

Can anyone please help me resolve this issue ?

I’m a little confused what you want to have stored in st.session_state.df. You have two different initialization scripts for it, a different one in each “page” function.

If resource_data_page() is executed first, you are going to have:
columns = ["Person_name", "Location", "AAAA", "BBBB", "CCCC", "DDDD", "EEEE", "FFFF"]

If task_data_page() is executed first, you are going to have:
columns = ["task_name", "completion_time", "resource_required", "n_cases"]

st.session_state.df is not going to get cleared out when you switch pages. Since you run resource_data_page() first, you do not have a column task_name when you execute task_data_page() next.

All I want to achieve is to create 4 data frames (forms) by using 4 different pages. Could you please let me know how I could go about creating this?

Don’t try to save them to the same place in session state. Use a different key for each dataframe.