引言

在使用Streamlit构建数据驱动的Web应用程序时,处理大型数据集(例如,包含数百万行的电子表格)时,性能优化是关键问题。本文将通过一个实际案例,展示如何利用Streamlit的高级特性来提高应用程序的响应速度和用户体验。

问题背景

假设我们有一个包含大约200万行的Excel文件,文件中包含产品信息,如PRODUCTID、PRODUCTNDC等。我们希望在Streamlit应用中提供一个用户友好的界面,允许用户通过产品ID或NDC代码进行筛选并查看结果。但是,每次用户选择不同的筛选条件时,应用都需要重新加载整个数据集,导致响应速度极慢。

代码实例与问题

下面是原始的代码结构:

import pandas as pd
import streamlit as st

# 读取数据
df = pd.read_excel('package.xlsx', engine='openpyxl', sheet_name='package')

# 创建筛选条件
options_pid = df['PRODUCTID'].unique().tolist()
selected_pid = st.sidebar.multiselect('Search product id', options_pid)
options_nid = df['PRODUCTNDC'].unique().tolist()
selected_nid = st.sidebar.multiselect('Search product ndc', options_nid)

# 筛选数据
if selected_pid:
    df = df[df["PRODUCTID"].isin(selected_pid)]
elif selected_nid:
    df = df[df["PRODUCTNDC"].isin(selected_nid)]

# 显示数据
st.dataframe(df)

该代码的问题在于,每次用户更改筛选条件时,整个数据集都会被重新加载和筛选,这对于大型数据集来说是非常低效的。

优化方案

1. 使用缓存

Streamlit提供了@st.cache_data装饰器,可以缓存函数的返回结果,避免重复计算或读取数据。

@st.cache_data
def load_excel_sheet():
    return pd.read_excel('package.xlsx', engine='openpyxl', sheet_name='package')

df = load_excel_sheet()

2. 转换数据格式

将Excel文件转换为Parquet格式可以大大提高读取速度和数据处理效率。Parquet文件支持列式存储,可以直接在读取时应用筛选条件。

import pyarrow as pa
import pyarrow.parquet as pq

# 转换Excel到Parquet
df = pd.read_excel('package.xlsx', engine='openpyxl', sheet_name='package')
df.to_parquet('package.parquet')

# 读取Parquet文件并筛选
def load_parquet_data():
    parquet_file = pq.ParquetFile('package.parquet')
    if selected_pid:
        return parquet_file.read(columns=['PRODUCTID', 'PRODUCTNDC']).to_pandas().query('PRODUCTID in @selected_pid')
    elif selected_nid:
        return parquet_file.read(columns=['PRODUCTID', 'PRODUCTNDC']).to_pandas().query('PRODUCTNDC in @selected_nid')
    else:
        return parquet_file.read(columns=['PRODUCTID', 'PRODUCTNDC']).to_pandas()

df = load_parquet_data()
st.dataframe(df)

总结

通过应用缓存机制和数据格式转换,我们可以显著提升Streamlit应用程序的性能。在处理大型数据集时,选择合适的数据存储格式和利用缓存策略不仅能提高用户体验,还能减少服务器负载。希望这个案例能为你提供一些实用的指导,帮助你优化自己的Streamlit应用。

更多推荐