Streamlit - selectbox로 선택한 값 유지시키기

    목차
반응형

해결 방법

`on_change` 파라미터에 session state에 선택한 값의 인덱스를 저장하는 함수를 넣고, 여기서 저장한 인덱스를 디폴트값으로 사용한다.

import streamlit as st

if "select_list" not in st.session_state:
    st.session_state.select_list = ["S 1", "S 2", "S 3"]

if "option_list" not in st.session_state:
    st.session_state.option_list = ["Option 1", "Option 2"]

if "selected" not in st.session_state:
    st.session_state.selected = 0

page_option = st.radio(
    "선택",
    st.session_state.option_list,
    index=0,
    key="page_option"
)

def update():
    st.session_state.selected = st.session_state.select_list.index(st.session_state.selected_option)

if page_option == "Option 1":
    selected_option = st.selectbox(
        "선택지",
        st.session_state.select_list,
        index=st.session_state.selected,
        key="selected_option",
        on_change=update
)

elif page_option == "Option 2":
    options = st.multiselect(
        '선택지들',
        ['S 1', 'S 2', 'S 3'], 
        key='options',
    )
    st.write(f"선택된 값들: {options}")

 

문제 상황

라디오버튼을 통해 선택한 것에 따라 페이지를 다르게 꾸미고 싶은 경우가 있다. 예를 들어, 아래처럼 Option 1을 선택하면 selectbox가 나오고, Option 2를 선택하면 multiselect가 나온다.

더보기
import streamlit as st

if "select_list" not in st.session_state:
    st.session_state.select_list = ["S 1", "S 2", "S 3"]

if "option_list" not in st.session_state:
    st.session_state.option_list = ["Option 1", "Option 2"]

page_option = st.radio(
    "선택",
    st.session_state.option_list,
    index=0,
    key="page_option"
)

if page_option == "Option 1":
    selected_option = st.selectbox(
        "선택지",
        st.session_state.select_list,
        key="selected_option",
    )
    st.write(f"선택된 값: {selected_option}")
elif page_option == "Option 2":
    options = st.multiselect(
        '선택지들',
        ['S 1', 'S 2', 'S 3'], 
        key='options',
    )
    st.write(f"선택된 값들: {options}")

이러면 Option 1에서 S 2를 선택했더라도 Option 2로 바꿨다가 다시 Option 1로 오면 선택했던 게 초기화되어 S 1이 선택되어있다. 나는 Option이 바뀌더라도 선택한 값은 계속 유지되었으면 했다.

해결 과정

해결 과정이라고 했지만 나의 실패 사례 모음이다.

 

1. 첫 번째 실패: session state에 index 업데이트 하기

if "selected" not in st.session_state:
    st.session_state.selected = 0
    
    
if page_option == "Option 1":
    selected_option = st.selectbox(
        "선택지",
        st.session_state.select_list,
        key="selected_option",
        index=st.session_state.selected
    )
    st.write(f"선택된 값: {selected_option}")
    st.session_state.selected = st.session_state.select_list.index(selected_option)

나의 생각

(1) `st.selectbox`에서 `index` 인자를 지정하면 기본값으로 해당하는 값을 보여준다.

(2) 그러면 index 값을 session state에 넣어놓고 `index` 인자에 집어넣으면 되지 않을까?

 

결과

이렇게 하면 Option 2 갔다가 1로 돌아와도 선택했던 게 살아있다!

하지만 selectbox에서 선택지를 바꾸면 다시 원래 값으로 되돌아간다. (다시 선택하면 바뀌긴 한다)

이유? 모르겠다. 진짜로.

 

 

2. 두 번째 실패: key로 인덱스 지정하기

if "selected" not in st.session_state:
    st.session_state.selected = "S 1"
    
    
if page_option == "Option 1":
    selected_option = st.selectbox(
        "선택지",
        st.session_state.select_list,
        key="selected",
        index=st.session_state.select_list.index(st.session_state.selected)
    )
    st.write(f"선택된 값: {selected_option}")

나의 생각

(1) `selectbox`의 `key` 인자를 주면 선택한 값이 자동으로 session state에 저장된다.

(2) 그러면 그 값을 다음 `index` 인자로 찾아서 넣어주면 되지 않을까?

 

결과

Option 2로 갔다 오면 초기화 되어있다.

 

이유

추측컨대, `if`문 안에 `selectbox`가 있기 때문에, Option 2를 선택하면 `selectbox`의 존재 자체가 지워지면서 session state의 메모리도 지워지는 게 아닌가 싶다. 근데 이상한건 Option 2를 선택했을 땐 잘 살아있다가 다시 Option 1을 선택하면 사라진다는 점...

 

728x90
반응형