streamlit -- 教程: 创建一个数据浏览器应用

翻译自用,侵删,未经允许禁止转载!

教程: 创建一个数据浏览器应用

如果您已经做到了这一点,那么您很有可能 安装streamlit 且跑过了 快速上手教程. 如果没有,建议您先看一下。

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

提示:

若您之前已经看过本教程并想一次性看到所有步骤, 完整脚本在此.


创建一个app

  1. 第一步,创建一个 uber_pickups.py.

  2. 打开uber_pickups.py 并添加以下代码:

    import streamlit as st
    import pandas as pd
    import numpy as np
    
  3. 每个好的app都有一个标题,我们也加一个:

    st.title('Uber pickups in NYC')
    
  4. 在终端执行以下指令来启动app:

    $ streamlit run uber_pickups.py
    
  5. 不出意外的话,app将自动打开你的浏览器的一个新tab页。


获取数据

Now that you have an app, the next thing you’ll need to do is fetch the Uber dataset for pickups and drop-offs in New York City.
现在我们有了一个app,接接下来我们需要做的就是获取 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 dataframe中,然后将数据的data列从文本转成datetime类。该函数接受一个参数(nrows),该参数指定了您想要加载到dataframe中的行数。

  2. 现在来测试下函数并检查输出吧,在你的函数下,添加以下代码:

    # Create a text element and let the reader know the data is loading.
    data_load_state = st.text('Loading data...')
    # Load 10,000 rows of data into the dataframe.
    data = load_data(10000)
    # Notify the reader that the data was successfully loaded.
    data_load_state.text('Loading data...done!')
    

    app的右上角的按钮会询问你是否重跑app。选择Always rerun,您每次保存时都会自动看到所做的更改。

事实证明,下载数据和将10,000行加载到数据框中需要花费很长时间。 将日期列转换为日期时间也不是一件容易的事。 您不希望每次更新应用程序时都重新加载数据–幸运的是,Streamlit允许您缓存数据。


轻松缓存

  1. load_data 前添加@st.cache装饰器:

    @st.cache
    def load_data(nrows):
    
  2. 然后保存,streamlit将自动重跑app. 由于这是您第一次使用@st.cache跑脚本, 你不会看到任何变换. 让我们稍微调整一下文件,以便您了解缓存的功能。

  3. 将 代码data_load_state.text('Loading data...done!') 改成:

    data_load_state.text("Done! (using st.cache)")
    
  4. 现在保存。看到你加进去的那一行了吗?如果你退一步看,这真的很神奇。一些神奇的事情正在幕后发生,只需要一行代码就可以激活它。


这是如何工作的?

让我们花点时间来看看 @st.cache 的实际工作.

当你使用Streamlit的cache注解来标记一个函数时,就告诉Streamlit 任何时候调用这个函数都需要检查三个东西:

  1. 组成函数提的实际字节码
  2. 这个函数依赖的代码、变量和文件
  3. 调用函数时传入的参数

如果Streamlit是第一次见到这些内容,它就会运行函数并在本地缓存中 保存结果。下一次函数再被调用时,如果以上三者没有变化,那么Streamlit就 可以直接利用缓存的值。

这种方式看起来很棒,但是也有一些局限:

  1. Streamlit将仅检查当前工作目录中的更改。 这意味着Streamlit仅检测已安装的Python库中的代码更新。
  2. 如果您的函数是不确定的(即,它的输出取决于随机数),或者如果它从外部时变源(例如,实时股票行情报价器服务)提取数据,那么缓存的值将是不明智的。
  3. 最后,由于缓存的值是按引用存储的(出于性能原因并能够支持TensorFlow之类的库),因此您不应更改缓存的函数的输出。 请注意,在这里,Streamlit足够聪明,可以检测到这些突变并显示响亮的警告,说明如何解决此问题。

尽管要牢记这些限制很重要,但在很多时候它们往往不会成为问题。 那些时候,此缓存确实具有变革性。

提示:
每当你的代码里存在一个耗时计算,请考虑使用@st.cache重构,如果可能的话。

现在您已经知道Streamlit的缓存工作原理,让我们回到Uber的客运数据。


检查原始数据

在开始使用原始数据之前,最好先查看一下要使用的原始数据。 让我们向应用添加子标题和原始数据的打印输出:

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

快速上手教程 我们了解到 st.write 将会呈现您传递给它的几乎所有内容。 在这种情况下,您要传入一个数据框并将其呈现为交互式表格。

st.write 尝试根据输入的数据类型做正确的事情。 如果它没有按照您的期望做,则可以使用专门的命令,例如 st.dataframe替代. 完整列表参见API reference.

或者,您可以使用专门的语句,例如 st.dataframe(),向您的应用添加特定的数据集。


绘制直方图

现在,您已经有机会查看数据集并观察可用数据,让我们更进一步,并绘制直方图,查看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. 现在使用 st.bar_chart() 方法来绘制这个直方图。

    st.bar_chart(hist_values)
    
  4. 保存脚本。 此直方图应立即显示在您的应用中。 快速浏览后,看来最忙的时间是17:00(下午5点)。

我们使用了 Streamlit 的原生 bar_chart() 方法来绘制图, 但我们需要知道streamlit是支持一些流行的图表库,如 Altair, Bokeh, Plotly, Matplotlib等. 完整列表参见 supported charting libraries.


在地图上绘制数据

在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'Map of all pickups at {hour_to_filter}:00')
    st.map(filtered_data)
    
  3. 您应该可以立即看到数据更新。

要绘制此地图,我们使用了Streamlit中内置的简单地图功能,但是如果您想可视化复杂的地图数据,建议您看一下st.deckgl_chart.


使用滑块过滤结果

在上一部分中,当您绘制地图时,用于过滤结果的时间被硬编码到脚本中,但是如果我们想让读者实时地动态过滤数据该怎么办? 您可以使用Streamlit的小部件。 使用 st.slider() 方法来添加一个滑块.

  1. 定位 hour_to_filter 并用以下代码替换:

    hour_to_filter = st.slider('hour', 0, 23, 17)  # min: 0h, max: 23h, default: 17h
    
  2. 使用滑块并实时观看地图更新。


使用复选框切换数据

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

  1. 定位以下代码:

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

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

我们确定您有自己的想法。 完成本教程的操作后,通过API reference可以查看Streamlit在我们的网站中公开的所有小部件 。


让我们放在一起

就这样,你坚持到了最后。这是我们的交互式应用程序的完整脚本。

提示:
如果您已经跳过了前面的步骤,那么在创建脚本之后,运行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
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)")

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)

Next
Previous

  • 0
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值