Streamlit使用session_state实现筛选后metric指标动态更新
现有代码错误点
- 对Streamlit运行逻辑理解有误:每次用户交互(点击按钮、输入内容)都会从头到尾重跑整个脚本,你把
result = 筛选后df的逻辑写在按钮点击的条件分支内,只有点击按钮的那次重跑能拿到筛选后的result,后续重跑时外层的result会被重置为初始全量df,外层渲染的指标永远拿不到筛选后的数据。 metric_employee函数逻辑完全混乱:判断session_state存在df就直接返回传入df的统计值,不存在才把初始df存入session_state,既没有同步筛选后的数据集,返回值类型还不统一(一个是统计数值,一个是DataFrame),根本起不到动态更新的作用。- 多余的存储逻辑:这个场景不需要把原始df存在session_state里,反而因为缓存了旧数据导致指标和筛选结果不同步。
实现方案
核心思路是把筛选后的结果持久化到st.session_state,让指标模块、结果展示模块始终读取同一份最新的数据集,直接基于当前数据集实时计算统计值即可,不需要多余的df缓存逻辑。
修正后的可运行代码如下:
import streamlit as st import pandas as pd # 此处保留你原本加载全量DataFrame的逻辑 # df = 你的原始数据加载代码 # 初始化默认展示全量数据 result = df if radioDB == "Search": regular_search_term = st.sidebar.text_input("Enter Search Term") if st.sidebar.button("search", key=1): # 拼接筛选条件,加na=False避免空值导致筛选报错 filter_mask = ( df['name'].str.contains(regular_search_term, na=False) | df['nickname'].str.contains(regular_search_term, na=False) | df['mother_name'].str.contains(regular_search_term, na=False) ) # 筛选后结果存入session_state,保证页面重跑时数据不丢失 st.session_state.filtered_result = df[filter_mask] # 优先读取session_state中存储的筛选结果,没有则使用全量数据 if "filtered_result" in st.session_state: result = st.session_state.filtered_result # 指标模块放在全局位置,永远基于最新的result计算 col1_m, col2_m, col3_m = st.columns(3) with col1_m: # 统计employee数量,加默认值0避免无匹配数据时报错 employee_count = result['status_type'].value_counts().get("employee", 0) st.markdown( f'<p class = "employee_metric"> {employee_count} employee</p>', unsafe_allow_html=True, ) # 结果展示模块 if radioDB == "Search": st.write(f"{result.shape[0]} Records ") display_aggrid(result)
修正注意事项
- 给所有
str.contains加上na=False参数,避免字段存在空值时筛选逻辑抛出异常 - 统计employee数量时用
.get("employee", 0),如果筛选结果中没有该类型的记录,直接返回0,不会因为键不存在报错 - 不需要单独封装存储df的metric函数,直接基于当前最新的result实时计算统计值即可,避免缓存旧数据导致数值不一致
- 如果需要清空筛选结果,可以加一个重置按钮,点击后执行
del st.session_state.filtered_result即可回到全量数据展示状态
内容的提问来源于stack exchange,提问作者DevLeb2022
相关产品推荐
相关产品推荐

