Hi, i am blocked inside streamlit.
I would like to get an app with multiple level of st.selectbox with each one depending on the other.
I did something like this but it seems not to work. How can I do to make each level of st.selectbox depends on each other results.
I mean I would like to have an app where we can input the number of funds and select on of them depending on filter.
I hope it is clear
Help appreciate
thx.
nombre_fonds = st.number_input('Nombre de fonds pour analyse:',
min_value=1,
max_value=15,
step=1
)
col1, col2, col3, col4, col5 = st.columns(5)
with col1:
selected_am = [st.selectbox("Choix de la société de gestion",
desc['FUND_MGMT_COMPANY'].sort_values().unique(),
index=3,
key='selected_am'+str(i)
)
for i in np.arange(nombre_fonds)]
with col2:
type_fonds = [st.selectbox("Nature du fonds",
desc.query("FUND_MGMT_COMPANY==@i")['FUND_TYP'].sort_values().unique(),
key='type_fonds'+str(i)
)
for i in selected_am]
if not type_fonds:
type_fonds = desc.query("FUND_MGMT_COMPANY==@selected_am")['FUND_TYP'].sort_values().unique()
classes = [['Toutes classes' ,
*desc.query("FUND_MGMT_COMPANY==@selec_am & FUND_TYP in @type")['FUND_ASSET_CLASS_FOCUS'].sort_values().unique()
] for selec_am in selected_am for type in type_fonds]
with col3:
selected_classe = [st.selectbox("Choix de la classe d'actif",
classes,
key='selected_classe'+str(i)
)
for i in np.arange(nombre_fonds)]
if selected_classe == 'Toutes classes':
fonds_sgp = desc.query("FUND_MGMT_COMPANY == @selected_am & FUND_TYP in @type_fonds")['LONG_COMP_NAME']
else:
fonds_sgp = desc.query("FUND_ASSET_CLASS_FOCUS==@selected_classe & FUND_MGMT_COMPANY == @selected_am & FUND_TYP in @type_fonds")['LONG_COMP_NAME']
with col4:
selected_fonds = [st.selectbox("Choix du fonds",
vl[fonds_sgp].columns.sort_values(),
key='selected_fonds'+str(i)
)
for i in np.arange(nombre_fonds)]
with col5:
weights = [st.number_input("Poids:",
min_value=0.0,
max_value=100.0,
value=100/nombre_fonds,
key='poids'+str(i)
)
for i in np.arange(nombre_fonds)]
Thanks for sharing the code snippet. I tried your code and it seems that the desc was not included in the code. Do you think you can share a few rows from this data.
I wrote up a dynamic filtering example on Stack Overflow a while ago. This is a little more general since it includes the option to change the order in which filters are selected, and uses multiselect instead of select. Let me know if you need the example simplified.
import streamlit as st
import pandas as pd
if 'df' not in st.session_state:
df = pd.DataFrame({
'Col1':['A','B','C','A'],
'Col2':[1,2,3,3],
'Col3':['a','a','b','c']
})
st.session_state.df = df
df = st.session_state.df
df_filtered = df.copy()
# Create a value in session state to track where the user is in the process of
# filling out the selections for the filters
if 'confirmed' not in st.session_state:
st.session_state.confirmed = -2
def confirm(index):
st.session_state.confirmed = index
st.write('Choose filters in the desired order. Reset filter selection to start over.')
filters = st.multiselect('Choose filters', df.columns, on_change=confirm, args=[-2])
if st.session_state.confirmed == -2:
st.button('Confirm', on_click=confirm, args=[-1], key='start')
if st.session_state.confirmed >= -1:
for i, col in enumerate(filters):
select = st.multiselect(col, df_filtered[col].unique(), key=f'col_{col}', on_change=confirm, args=[i-1])
if select != []:
df_filtered = df_filtered[df_filtered[col].isin(select)]
if i > st.session_state.confirmed:
st.button('Confirm', on_click=confirm, args=[i])
break
cols = st.columns(2)
cols[0].write(df)
cols[1].write(df_filtered)
it is not precisely what I want…
I would like to have n filter with exactly the same input with n determined by the user.
I would like to proceed as a funnel at each step of the selection process ie I would like multiple level of the line with the multiple option (the number of lines are given in the option ‘Nombre de fonds pour analyse’ and from this process to get a variable with all the name “fonds” that was selected.
I add that I would like also that in certain option I would like to add a new option which are ‘all’ where the choice is deactivated.
I hope it is clearer now.
Thx.
Here is a different example. There are multiple ways to accomplish this. You can pass unique keys instead of unique labels if you want. If you do use keys, you can get at the result directly from session state instead of collecting the selections like I do here. Hopefully, this provides some direction, though.
import streamlit as st
import pandas as pd
import numpy as np
if 'df' not in st.session_state:
st.session_state.df = pd.DataFrame(np.random.randint(0,10,size=(100,4)), columns = ['A','B','C','D'])
df = st.session_state.df
st.write(df)
n = st.number_input('Number of selections', step=1)
def selection_row(i):
cols = st.columns(3)
a = cols[0].selectbox(f'A ({i})',df['A'].unique())
b = cols[1].selectbox(f'B ({i})',df[df['A']==a]['B'].unique())
c = cols[2].selectbox(f'C ({i})',df[df['A']==a][df['B']==b]['C'].unique())
return (a,b,c)
selections = []
for row in range(n):
selections.append(selection_row(row))
st.write('Result:')
st.dataframe(selections)