Pass Filtered Dataframe Through Three Dropdown levels

I’ve started working with streamlit & python very recently, this could be a very basic question and not sure if I can post it here or should use StackExchange for help. But any help or direction is appreciated.

Trying to filter dataframes to show different views. It involves selecting values from three dropdown values and one view without selecting any.

Each filter shows visualization for the filtered dataframe

Sample Code:


def select_1(source_df: pd.DataFrame) -> pd.DataFrame:
    selected_mgr = st.multiselect(
        "Select Manager Name for further exploration below",
        source_df["manager"].unique(),
    )
    selected_1_df = source_df[(source_df["manager"].isin(selected_mgr))]
    if selected_mgr:
        st.write('You have selected', selected_mgr)
    return selected_1_df


def select_2(selected_1_df: pd.DataFrame) -> pd.DataFrame:
    selected_emp = st.multiselect(
        "Select Consultant Name for further exploration below",
        selected_1_df["employee"].unique(),
    )
    selected_2_df = selected_1_df[(selected_1_df["employee"].isin(selected_emp))]
    if selected_emp:
        st.write('You have selected', selected_emp)
    return selected_2_df


def select_3(selected_2_df) -> pd.DataFrame:
    selected_month = st.multiselect(
        "Select one or more Months for further exploration below",
        selected_2_df["month"].unique(),
    )
    selected_3_df = selected_2_df[(selected_2_df["month"].isin(selected_month))]
    if selected_month:
        st.write('you have selected', selected_month)
    return selected_3_df


    source_df = df

    ## Calling functions for st.multiselect
    selected_1_df = select_1(source_df)
    selected_2_df = select_2(selected_1_df )
    selected_3_df = select_3(selected_2_df ) 

   if not selected_1_df.empty:
     do some stuff(selected_1_df)
   elif not selected_2_df.empty:
     do some stuff (selected_2_df)
   elif not selected_3_df.empty
     do some stuff (selected_3_df)
   else:
     do some stuff(source_df)

The problem I’m facing is, I’m unable to pass the first filtered dataframe to the next. Different approach or a solution to this also would help.

I’m doing something similar, without a problem, but I’m handling it all as successive steps within a single function, rather than chaining together the outputs from successive functions like you’re doing here.

Here’s the precise code that’s letting me correctly apply a date range and two multi-selects, in real-time (as of today :wink: ):

def df_filtered(
    df: pd.DataFrame,  # Source dataframe
    f_date_range: [int, int],  # Current value of an ST date slider
    f_manager: list = [],  # Current value of an ST multi-select
    f_program: list = [],  # Current value of another ST multi-select
) -> pd.DataFrame:
    dff = df.loc[f_date_range[0] : f_date_range[1]].reset_index(drop=True)
    if len(f_manager) > 0:
        dff = dff.loc[(dff["owner"].isin(f_manager))].reset_index(drop=True)
    if len(f_program) > 0:
        dff = dff.loc[(dff["program"].isin(f_program))].reset_index(drop=True)
    return dff

To call it, I just pass in the dataframe in question, and then the outputs from my ST widgets:

dff = df_filtered(df, f_date_range=ctl_date_slider, f_manager=ctl_manager_multi, f_program=ctl_program_multi)

Dataframes are notoriously finicky, especially when it comes to which changes are being applied in place, and which are only applied to an implicit copy. The extra .reset_index(drop=True) in my statements are the kind of wrinkle that can easily throw off something that seems really simple, in concept – it took me quite a while to sort out the exact details of a process that works correctly in practice.

1 Like

(LOL…just noticed that this question is already 10 months old. I guess this suggestion is for future reference, for anyone else who finds themselves on this page from Google.)

1 Like