Create an app

如果你已经做到了这一步,很可能你已经安装了Streamlit并且完成了基础概念高级概念的学习。如果没有,现在是一个很好的时机去了解一下。

学习如何使用Streamlit的最简单方法是自己尝试。在阅读本指南时,测试每种方法。只要你的应用程序在运行,每次你向脚本添加新元素并保存时,Streamlit的UI都会询问你是否要重新运行应用程序并查看更改。这使你可以在一个快速的交互循环中工作:你编写一些代码,保存它,查看输出,再编写一些,依此类推,直到你对结果满意为止。目标是使用Streamlit为你的数据或模型创建一个交互式应用程序,并在此过程中使用Streamlit来审查、调试、完善和分享你的代码。

在本指南中,您将使用Streamlit的核心功能创建一个交互式应用程序;探索纽约市的Uber接送公共数据集。完成后,您将了解如何获取和缓存数据、绘制图表、在地图上绘制信息,以及使用滑块等交互式小部件来过滤结果。

star

提示

如果你想跳过前面的内容,直接查看所有内容,完整的脚本如下所示

Streamlit 不仅仅是一种制作数据应用的方式,它还是一个创作者社区,大家在这里分享他们的应用和想法,并互相帮助使工作变得更好。请加入我们的社区论坛。我们喜欢听到您的问题、想法,并帮助您解决错误——今天就来看看吧!

  1. 第一步是创建一个新的Python脚本。我们将其命名为 uber_pickups.py

  2. 在你喜欢的IDE或文本编辑器中打开uber_pickups.py,然后添加以下行:

    import streamlit as st import pandas as pd import numpy as np
  3. 每个好的应用都有一个标题,所以让我们添加一个:

    st.title('Uber pickups in NYC')
  4. 现在是时候从命令行运行 Streamlit 了:

    streamlit run uber_pickups.py

    运行 Streamlit 应用程序与运行其他 Python 脚本没有什么不同。每当您需要查看应用程序时,都可以使用此命令。

    star

    提示

    您知道您还可以将 URL 传递给 streamlit run 吗?当与 GitHub Gists 结合使用时,这非常有用。例如:

    streamlit run https://raw.githubusercontent.com/streamlit/demo-uber-nyc-pickups/master/streamlit_app.py
  5. 通常情况下,应用程序应该会自动在浏览器的新标签页中打开。

现在你有了一个应用程序,接下来你需要做的是获取纽约市的Uber数据集,用于接送服务。

  1. 让我们从编写一个函数来加载数据开始。将此代码添加到您的脚本中:

    DATE_COLUMN = 'date/time' DATA_URL = ('https://s3-us-west-2.amazonaws.com/' 'streamlit-demo-data/uber-raw-data-sep14.csv.gz') def load_data(nrows): data = pd.read_csv(DATA_URL, nrows=nrows) lowercase = lambda x: str(x).lower() data.rename(lowercase, axis='columns', inplace=True) data[DATE_COLUMN] = pd.to_datetime(data[DATE_COLUMN]) return data

    您会注意到load_data是一个简单的旧函数,它下载一些数据,将其放入Pandas数据框中,并将日期列从文本转换为日期时间。该函数接受一个参数(nrows),它指定您要加载到数据框中的行数。

  2. 现在让我们测试这个函数并查看输出。在你的函数下面,添加这些行:

    # 创建一个文本元素,让读者知道数据正在加载。 data_load_state = st.text('Loading data...') # 将10,000行数据加载到数据框中。 data = load_data(10000) # 通知读者数据已成功加载。 data_load_state.text('Loading data...done!')

    你会在应用程序的右上角看到几个按钮,询问你是否要重新运行应用程序。选择总是重新运行,每次保存时你都会看到你的更改自动更新。

好吧,这有点令人失望...

事实证明,下载数据并将10,000行加载到数据框中需要很长时间。将日期列转换为日期时间也不是一件快速的工作。你不希望每次应用程序更新时都重新加载数据——幸运的是,Streamlit允许你缓存数据。

  1. 尝试在 load_data 声明前添加 @st.cache_data

    @st.cache_data def load_data(nrows):
  2. 然后保存脚本,Streamlit 会自动重新运行你的应用程序。由于这是你第一次使用 @st.cache_data 运行脚本,你不会看到任何变化。让我们再稍微调整一下你的文件,以便你可以看到缓存的力量。

  3. 将行 data_load_state.text('Loading data...done!') 替换为以下内容:

    data_load_state.text("Done! (using st.cache_data)")
  4. 现在保存。看到你添加的那一行立即出现了吗?如果你退一步想想,这实际上相当神奇。在幕后发生了一些神奇的事情,而激活它只需要一行代码。

让我们花几分钟时间讨论一下@st.cache_data实际上是如何工作的。

当你用Streamlit的缓存注解标记一个函数时,它会告诉Streamlit每当调用该函数时,应该检查两件事:

  1. 您用于函数调用的输入参数。
  2. 函数内部的代码。

如果这是Streamlit第一次看到这两个项目,并且这些值完全相同,且以这种确切的组合出现,它会运行该函数并将结果存储在本地缓存中。下次调用该函数时,如果这两个值没有改变,那么Streamlit就知道它可以完全跳过执行该函数。相反,它会从本地缓存中读取输出并将其传递给调用者——就像魔法一样。

“但是,等一下,”你对自己说,“这听起来好得令人难以置信。所有这些令人惊叹的东西有什么限制呢?”

嗯,有几点:

  1. Streamlit 只会检查当前工作目录内的更改。 如果你升级了一个 Python 库,Streamlit 的缓存只有在 该库安装在工作目录内时才会注意到这一点。
  2. 如果你的函数不是确定性的(即其输出依赖于随机数),或者如果它从外部随时间变化的源(例如,实时股票市场行情服务)中提取数据,缓存的值将不会变得更聪明。
  3. 最后,你应该避免修改使用st.cache_data缓存的函数输出,因为缓存的值是通过引用存储的。

虽然这些限制很重要,需要牢记,但它们往往在大多数时候不会成为问题。在那些时候,这个缓存确实具有变革性。

star

提示

每当你的代码中有长时间运行的计算时,考虑重构它以便尽可能使用@st.cache_data。请阅读Caching了解更多详情。

既然你已经了解了如何使用Streamlit进行缓存,让我们回到Uber的接客数据。

在开始处理数据之前,查看原始数据总是一个好主意。让我们在应用程序中添加一个子标题和原始数据的打印输出:

st.subheader('Raw data') st.write(data)

基本概念指南中,您了解到st.write可以渲染几乎所有传递给它的内容。在这种情况下,您传递了一个数据框,它被渲染为一个交互式表格。

st.write 尝试根据输入的数据类型做正确的事情。如果它没有按照你的预期工作,你可以使用专门的命令,比如 st.dataframe。完整的列表,请参见 API 参考

既然你已经有机会查看数据集并观察可用的内容,让我们更进一步,绘制一个直方图,看看在纽约市Uber最繁忙的时间是什么时候。

  1. 首先,让我们在原始数据部分下方添加一个子标题:

    st.subheader('Number of pickups by hour')
  2. 使用 NumPy 生成一个按小时分箱的接载时间直方图:

    hist_values = np.histogram( data[DATE_COLUMN].dt.hour, bins=24, range=(0,24))[0]
  3. 现在,让我们使用 Streamlit 的 st.bar_chart() 方法来绘制这个 直方图。

    st.bar_chart(hist_values)
  4. 保存您的脚本。这个直方图应该会立即显示在您的应用程序中。 经过快速查看,看起来最繁忙的时间是17:00(下午5点)。

为了绘制这个图表,我们使用了Streamlit的原生bar_chart()方法,但重要的是要知道Streamlit支持更复杂的图表库,如Altair、Bokeh、Plotly、Matplotlib等。完整列表请参见支持的图表库

使用直方图与Uber的数据集帮助我们确定了最繁忙的接送时间,但如果我们想弄清楚接送在整个城市中的集中位置呢?虽然你可以使用条形图来显示这些数据,但除非你对城市的纬度和经度坐标非常熟悉,否则不容易解释。为了显示接送集中情况,让我们使用Streamlit的st.map()函数将数据叠加在纽约市的地图上。

  1. 为该部分添加一个子标题:

    st.subheader('Map of all pickups')
  2. 使用 st.map() 函数来绘制数据:

    st.map(data)
  3. 保存您的脚本。地图是完全交互式的。尝试通过平移或稍微放大来体验。

在绘制了直方图之后,您确定Uber接客最繁忙的时间是17:00。让我们重新绘制地图以显示17:00时的接客集中情况。

  1. 找到以下代码片段:

    st.subheader('Map of all pickups') st.map(data)
  2. 替换为:

    hour_to_filter = 17 filtered_data = data[data[DATE_COLUMN].dt.hour == hour_to_filter] st.subheader(f'所有在 {hour_to_filter}:00 的接载地点地图') st.map(filtered_data)
  3. 你应该会看到数据立即更新。

为了绘制这张地图,我们使用了Streamlit内置的st.map函数,但如果您想可视化复杂的地图数据,我们建议您查看st.pydeck_chart

在上一节中,当你绘制地图时,用于过滤结果的时间是硬编码在脚本中的,但如果我们想让读者实时动态过滤数据呢?使用Streamlit的小部件,你可以做到。让我们使用st.slider()方法向应用程序添加一个滑块。

  1. 找到 hour_to_filter 并将其替换为以下代码片段:

    hour_to_filter = st.slider('hour', 0, 23, 17) # 最小值:0小时,最大值:23小时,默认值:17小时
  2. 使用滑块并实时观察地图更新。

滑块只是动态改变应用程序组成的一种方式。 让我们使用st.checkbox函数来为你的应用程序添加一个 复选框。我们将使用这个复选框来显示/隐藏应用程序顶部的原始数据 表格。

  1. 找到这些行:

    st.subheader('Raw data') st.write(data)
  2. 用以下代码替换这些行:

    if st.checkbox('Show raw data'): st.subheader('Raw data') st.write(data)

我们相信您有自己的想法。当您完成本教程后,请查看Streamlit在我们的API参考中公开的所有小部件。

就是这样,你已经完成了。这是我们交互式应用程序的完整脚本。

star

提示

如果你已经跳过了前面的步骤,在你创建了脚本之后,运行Streamlit的命令是streamlit run [app name]

import streamlit as st import pandas as pd import numpy as np st.title('Uber pickups in NYC') DATE_COLUMN = 'date/time' DATA_URL = ('https://s3-us-west-2.amazonaws.com/' 'streamlit-demo-data/uber-raw-data-sep14.csv.gz') @st.cache_data def load_data(nrows): data = pd.read_csv(DATA_URL, nrows=nrows) lowercase = lambda x: str(x).lower() data.rename(lowercase, axis='columns', inplace=True) data[DATE_COLUMN] = pd.to_datetime(data[DATE_COLUMN]) return data data_load_state = st.text('Loading data...') data = load_data(10000) data_load_state.text("Done! (using st.cache_data)") if st.checkbox('Show raw data'): st.subheader('Raw data') st.write(data) st.subheader('Number of pickups by hour') hist_values = np.histogram(data[DATE_COLUMN].dt.hour, bins=24, range=(0,24))[0] st.bar_chart(hist_values) # Some number in the range 0-23 hour_to_filter = st.slider('hour', 0, 23, 17) filtered_data = data[data[DATE_COLUMN].dt.hour == hour_to_filter] st.subheader('Map of all pickups at %s:00' % hour_to_filter) st.map(filtered_data)

在你构建了一个Streamlit应用之后,是时候分享它了!为了向全世界展示它,你可以使用Streamlit Community Cloud免费部署、管理和分享你的应用。

它通过3个简单的步骤工作:

  1. 将您的应用程序放在一个公共的GitHub仓库中(并确保它有一个requirements.txt文件!)
  2. 登录 share.streamlit.io
  3. 点击 'Deploy an app' 然后粘贴你的 GitHub URL

就是这样!🎈 你现在有了一个可以公开部署的应用程序,可以与全世界分享。点击了解更多关于如何使用Streamlit社区云的信息。

这就是入门指南,现在你可以去构建自己的应用程序了!如果你遇到困难,这里有几件事你可以做。

  • 查看我们的社区论坛并发布问题
  • 通过命令行快速获取帮助,使用 streamlit help
  • 浏览我们的知识库,获取提示、逐步教程和文章,这些内容将回答您关于创建和部署Streamlit应用程序的问题。
  • 阅读更多文档!查看:
    • 概念 了解诸如缓存、主题化和为应用添加状态性等内容。
    • API参考 查看每个Streamlit命令的示例。
forum

还有问题吗?

我们的 论坛 充满了有用的信息和Streamlit专家。