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)]
Hi @Jacques2101
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.
Best regards,
Chanin
here is the first 10 lines of desc data:
FUND_MGMT_COMPANY LONG_COMP_NAME FUND_TYP FUND_ASSET_CLASS_FOCUS FUND_TYP FUND_ASSET_CLASS_FOCUS
0 Ossiam SA OSSIAM EUROPE ESG MACHINE LEARNING ETF Equity ETF Equity
1 Ossiam SA OSSIAM Stoxx Europe 600 ESG Broad Market Equal... ETF Equity ETF Equity
2 Allianz Global Investors GmbH Brunner Investment Trust PLC/The Investment Trust Equity Investment Trust Equity
3 Allianz Global Investors GmbH Allianz Technology Trust PLC Investment Trust Equity Investment Trust Equity
4 BNP Paribas Asset Management Luxembourg SA BNP Paribas Easy FTSE EPRA/NAREIT Eurozone Cap... ETF Equity ETF Equity
5 BNP Paribas Asset Management Luxembourg SA BNP Paribas Easy Low Carbon 100 PAB ETF Equity ETF Equity
6 Ossiam SA OSSIAM RISK WEIGHTED ENHANCED COMMODITY EX GRA... ETF Commodity ETF Commodity
7 Groupama Asset Management SA/France Groupama Asset Management Retraite Equilbre Fund of Fund Mixed Allocation Fund of Fund Mixed Allocation
8 Groupama Asset Management SA/France Groupama Asset Management Retraite Dynamique Fund of Fund Mixed Allocation Fund of Fund Mixed Allocation
9 Ecofi Investissements SA Ecofi Investissements Epargne Ethique Actions SICAV Equity SICAV Equity```
Maybe to be more explicit about my purpose:
i would like to select multiple data that are filtered at each step ie by:
-
the asset management company name (FUND_MGMT_COMPANY)
-
Nature of the fund (FUND_TYP)
-
choice of the asset class (FUND_ASSET_CLASS_FOCUS)
That gives the name of the funds and the weight which I need to enter.
and do this for I = 1 to n (the number of funds)
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)
Does that help at all? Hereâs the original.
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)