Streamlit应用开发:数据上传、图表与筛选实战

0 阅读10分钟

构建您的第一个Streamlit应用:上传、图表与筛选(第一部分)

在本教程中,您将学习如何将一个简单的Streamlit脚本转变为一个强大的数据探索工具。您将创建一个能够加载并分析数据集、交互式可视化数据模式、并筛选导出结果的应用——全程无需编写JavaScript。

本课程是Streamlit应用系列的一部分:

  • Streamlit入门:学习部件、布局与缓存
  • 构建您的第一个Streamlit应用:上传、图表与筛选(第一部分)(本篇教程)
  • 构建您的第一个Streamlit应用:上传、图表与筛选(第二部分)
  • 将Streamlit与某云数据平台集成,构建实时云端数据应用(第一部分)
  • 将Streamlit与某云数据平台集成,构建实时云端数据应用(第二部分)

若要学习如何使用Streamlit无缝上传、探索、可视化和导出数据,请继续阅读。

为何首选数据探索器?

在深入模型、仪表盘或某云数据平台连接之前,每个数据项目都始于一个通用步骤——理解数据。无论您是验证特征工程的数据科学家、清理原始CSV的分析师,还是检查数据漂移的机器学习工程师,您总是需要一种快速、可靠的方式来查看数据集。

“数据探索器”模式正是为此最通用的基础。它简单到足以进行快速实验,又强大到可以成为可复用的内部工具。仅需几个Streamlit原语——文件上传、图表和缓存——您就能构建一个轻量级界面,节省数小时的笔记本调试和邮件往来。

Streamlit在此处表现出色,因为它消除了代码与洞察之间的摩擦。您可以将您喜爱的库(例如pandas、Altair、matplotlib)直接连接到UI部件,让队友在不接触代码的情况下与您的逻辑交互。不再分享静态报告,而是分享一个应用:用户可以按自己的方式探索、切片和导出。

本课聚焦于此——一个精简但真实的示例,展示了为何Streamlit已成为分析学和机器学习原型开发的首选工具。

图2: 数据探索器作为洞察的共享工具,连接数据科学家、数据分析师、数据工程师和教育者于一个协作环境中——桥接分析、工程和学习,实现统一的数据驱动决策。

配置您的开发环境

要遵循本指南,您需要在系统上安装Streamlit及几个支持库。

幸运的是,Streamlit可以通过pip安装,并适用于所有主流平台。

pip install "streamlit>=1.38,<2" "pandas>=2.2,<3" altair>=5.2,<6

安装后,验证一切配置正确:

python -c "import streamlit, pandas; print(streamlit.__version__, pandas.__version__)"

您应该在终端中看到版本号,确认您的环境已准备就绪。

辅助模块回顾:理解数据与可视化工具

在深入lesson2_main.py之前,让我们重新审视那些为应用默默提供支持的轻量级辅助模块。这些模块使主Streamlit文件保持清洁和模块化,将配置、数据访问和可视化关注点分离。

pyimagesearch/data_loader.py:读取与复用数据集

该模块抽象了文件读取逻辑,以便您在所有课程中复用相同的加载器。

from functools import lru_cache
import pandas as pd
from typing import Optional, IO

导入库非常精简:

  • pandas用于读取CSV文件。
  • functools中的lru_cache用于简单的内存缓存——这样,如果重复加载同一个文件(每次重新运行后),不会每次都从磁盘重新读取。
  • 类型提示(Optional, IO)帮助编辑器(如VS Code)提供自动补全和静态检查。
@lru_cache(maxsize=1)
def load_iris_sample(path: str) -> pd.DataFrame:
    return pd.read_csv(path)

此函数读取捆绑的鸢尾花样本数据集。 @lru_cache(maxsize=1)装饰器确保,即使Streamlit在每个部件更改时重新运行脚本,CSV文件在每个Python进程中仅被加载一次。 如果切换数据集或重启应用,缓存会自动重置。

def load_uploaded_csv(file_obj: IO[bytes]) -> pd.DataFrame:
    return pd.read_csv(file_obj)

第二个辅助函数处理应用中任意的CSV上传。它接受st.file_uploader返回的类文件对象,并将其直接读入DataFrame。此处未使用缓存——每个上传的文件都是唯一的,按文件对象缓存可能会导致用户或会话间结果混淆。

图4: 一个简单的数据加载流程——无论是通过load_iris_sample()使用内置样本,还是通过load_uploaded_csv()上传自定义CSV——两者都馈入一个共享的DataFrame,驱动应用UI。

pyimagesearch/config.py:集中式设置

from dataclasses import dataclass
import os

config.py存储多个课程复用的常量和配置逻辑。 对于本课,只有一个字段是重要的:

default_sample_path: str = os.path.join("data", "iris_sample.csv")

所有其他字段均与某云数据平台连接性有关,并将在后续课程中发挥作用。 即使将小值集中在此,也能使您的Streamlit脚本保持声明式且整洁。

应用自定义主题:增添一丝精致

在深入完整的Streamlit应用之前,让我们让它看起来更专业一些。默认情况下,Streamlit使用浅色主题,但只需几行配置,您就可以完全重新设计应用样式。

Streamlit中的主题通过存储在.streamlit/目录下的简单TOML文件控制。这允许您全局自定义背景、文本和强调色,无需CSS。

创建主题文件

在您的项目根目录下,如果.streamlit文件夹不存在,请创建它,然后添加一个名为config.toml的新文件:

[theme]
base = "dark"
primaryColor = "#FF4B4B"
backgroundColor = "#0E1117"
secondaryBackgroundColor = "#262730"
textColor = "#FAFAFA"

此配置应用了一个现代深色主题:

  • base:将整个应用切换到深色模式。
  • primaryColor:定义强调色(按钮和高亮颜色)。
  • backgroundColorsecondaryBackgroundColor:控制页面和侧边栏颜色。
  • textColor:设置所有部件和标签的前景色。

Streamlit如何加载它

当您运行时,Streamlit会自动检测并应用.streamlit/config.toml文件:

streamlit run lesson2_main.py

无需额外的导入或代码更改。

这非常理想,因为主题设置保持纯粹的声明式——您可以调整颜色、字体或布局行为,而无需触及您的Python脚本。

提示:扩展主题

您还可以在此处设置其他UI范围的参数(例如,页面布局和字体样式):

[server]
headless = true
enableCORS = false

[client]
toolbarMode = "minimal"

这些选项在部署到云环境或将应用嵌入内部仪表盘时可能很有用(请根据您的安全需求仔细审查CORS设置)。

至此,您的应用感觉更加协调——深色背景使数据表和图表更加突出,强调色也与您的视觉风格保持一致。

接下来,我们将逐步构建第二课的应用本身——逐页解析lesson2_main.py代码,解释导航、数据处理和可视化如何协同工作。

") st.sidebar.caption("第二课演示应用")


此处,您使用**侧边栏单选按钮**引入了一个简单的单页面导航模式。
每个选择设置变量`page`,您将在后续使用`if page == ...`代码块渲染相应部分。
这种模式感觉像是多个页面,但仍在一个文件中,非常适合在过渡到`pages/`文件夹结构之前的小型原型。

**图8:** 侧边栏显示导航项列表,其中“概览”被选中

#### 显示概览页面

```python
base_df = get_base_data()

if page == "概览":
    st.header("概览")
    st.write("基础数据集预览:")
    st.dataframe(base_df.head())
    st.write("形状:", base_df.shape)
    st.code("""@st.cache_data 缓存返回值以加速重新运行。""")

当选择"概览"时:

  • 您调用get_base_data()一次并将其结果存储在base_df中。
  • 您显示一个标题、数据集的前五行预览及其形状(行×列)。
  • 最后,您包含一个代码片段提醒用户关于缓存的知识,强化入门课程中的关键概念。

此页面既作为完整性检查,也作为用户在探索更深页面之前的定位点

图9: 概览页面显示鸢尾花数据集预览表和形状信息

此结构为何重要

即使在这个阶段,也能看到3个最佳实践:

  • 模块化:数据加载被抽象成一个函数,因此未来只需替换路径即可更换数据集。
  • 状态简洁:屏幕上显示的一切都可以从缓存的DataFrame重新派生。
  • 声明式UI:布局通过您想显示什么来描述,而不是如何渲染它

这个干净的基础让您可以扩展到更复杂的部分(即图表、筛选器和上传),而无需重构。

接下来,我们将扩展到探索页面,您将在其中使用Altair添加第一个交互式图表。


探索页面:交互式散点图

探索页面是本课第一个真正的“顿悟”时刻,您将从静态表格转向实时的、交互式图表。此页面允许用户使用来自visualization.py的可复用辅助函数iris_feature_scatter()生成的散点图,比较数据集的两个数值特征。

代码块

elif page == "探索":
    st.header("交互式散点图")
    numeric_cols = [c for c in base_df.columns if c not in {"species"}]
    x = st.selectbox("X轴", numeric_cols, index=0)
    y = st.selectbox("Y轴", numeric_cols, index=1)
    chart = iris_feature_scatter(base_df, x, y)
    st.altair_chart(chart, use_container_width=True)

工作原理

  • 页面标题st.header("交互式散点图")创建一个清晰的视觉分隔,并标记当前页面上下文。
  • 选择数值列numeric_cols = [c for c in base_df.columns if c not in {"species"}]。此处,我们动态检测所有数值列,过滤掉分类型目标列species。这确保用户只选择适合绘图的变量。
  • 轴选择部件:两个下拉菜单让用户选择在X轴和Y轴上绘制哪些数值特征。每次用户更改选择时,Streamlit都会重新运行脚本,即时更新图表
  • 渲染图表:辅助函数构建带有内置悬停工具提示和流畅交互性的Altair图表。传递use_container_width=True确保图表适应页面的完整列宽,这对于在各种屏幕尺寸上查看仪表盘至关重要。

为何在此使用辅助函数

将绘图逻辑封装在iris_feature_scatter()中可以使主脚本保持可读性并避免重复。 您以后可以为其他类鸢尾花数据集复用同一个辅助函数,甚至将其参数化,以通过用户选择的分类型列(例如color_col)为点着色。

图10: 探索页面截图,显示散点图上方的两个下拉菜单(“X轴”和“Y轴”),悬停在点上时可显示工具提示。

您所学到的

  • 如何以声明方式将部件连接到可视化。
  • Streamlit的重新运行模型如何即时反映状态变化。
  • 为何Altair非常适合快速、交互式的探索性数据分析(EDA)界面。

接下来,我们将在第二部分继续讲解上传页面,用户可以在该页面导入自己的CSV文件,并在应用中直接预览或分析它们。FINISHED