「本文参与少数派 2019 年度征文 + 效率有心得」

不用学前端编程,你就能用 Python 简单高效写出漂亮的交互式 Web 应用,将你的数据分析成果立即展示给团队和客户。

从我开始折腾数据分析工具的那一天,就没有想明白一件事儿 —— 为什么我打算把数据分析的成果做成一个应用,这么难?

其实我需要的核心功能,无非是在网页上接收用户输入,然后做分析处理,把分析结果反馈给用户,完事儿。

可是这谈何容易?

很多人都会笑着告诉你,这得学前端编程, HTML + Javascript 了解一下吧!

什么?你还需要在后台做数据分析?那你就得学 Web 框架了。

你说喜欢 Python ?那就学个 Django 或者 Flask 好了。

我也不是没有看过 Django 和 Flask 的教程,还曾经付费学习过。光是配置环境,就得循序渐进学一堆东西。作为学习的中间成果,我还写了这篇《 如何用 Python 做 Web 开发?——Django 环境配置 》分享给你。

问题是我在学习中,提不起真正的兴趣。

因为教程里讲的那些功能,我根本不关心。

核心的功能,我早已实现了。我只是希望把输入输出弄成网页形式,方便用户来用。

我为什么要理解那么多的概念?为什么一定要跟那么繁重的数据库操作打交道?为什么几乎所有的样例,都要教我如何做一个 blog ?

我要是想用 blog ,可以直接注册一个免费的啊!难道我要自己开发?

你的教程为什么不干脆教我怎么把数据科学的分析结果,利用这些技术快速变成一个产品?

但是人家写书和做教程的人,就是不疾不徐,坚持一定要教会你,如何做一个 blog 出来……

我仿佛看见达芬奇的老师教学生画鸡蛋一样。

我相信,这绝不仅仅是我一个人的痛点。

我们都希望 尽快 把数据分析结果,或是其他的交互功能发布出来,和用户交流。但是因为缺乏这样的简单 Web 包裹,我们不得不每次都给别人展示一个包含了代码的 Jupyter Notebook 。

那些不懂编程的用户,看到代码,就会觉得不适。再看到改变一个输入都需要编程(其实就是改语句中的一个赋值),立刻就决定不玩儿了。

万万没想到,这个痛点,如此容易就解决了。

我用纯 Python 脚本写了个 Web 应用。

我编写的程序里,没有一丝半毫的 Web 框架,Javascript,甚至是 HTML 。

这玩意儿能用吗?

你自己来试试看。

请你打开浏览器,输入 以下链接

https://helloworld-streamlit.herokuapp.com/

你会看到下面的初始化界面。

初始化完毕之后,页面会分成左右两栏。左面是两个下拉候选框,分别让你指定需要分析的数据范围。

上面一个,是事件类型;

下面一个,是事件发生归属地。

如果你看过《 如何用 Python 和循环神经网络预测严重交通拥堵? 》,应该对这个数据集很熟悉。

只不过,当时我们更注重的,是用循环神经网络搭建了一个严重拥堵事件预测模型。

而今天,我们是要进行探索性数据分析,也就是根据我们感兴趣的目标,对数据进行整理操作,然后可视化显示。

选定之后,你会看到右侧提示两个信息:

  • 你筛选之后,数据框包含行数;
  • 在层叠地图上的可视化结果。
  • 麻雀虽小,五脏俱全。

    虽然咱们这个 Web 应用很简单,不过交互分析该有的功能和流程,基本上都涵盖了。

    你可能会问:

    王老师,编这么一个应用出来,不简单吧?

    学完这篇教程,你就能 自己开发出 这样一个应用来。

    我把这个应用的全部源代码,都为你存储到了 Github 上。请你访问 这个网址 获取。

    可以看到,一共包含了 4 个文件。

    有意思的是,其中 3 个,包括:

  • Procfile
  • setup.sh
  • requirements.txt
  • 都只是部署到远程服务器时,需要用到的配置文件而已。

    这些文件的具体使用方法,咱们后面会说明。

    也就是说,只有最后一个 helloworld.py 是主角,它包含了实现咱们 全部交互式数据分析功能 的 Python 脚本文件。

    这代码,少说也得有几百行吧?

    别担心,打开来看看:

    上面这张截图,就已经包含了实现交互数据分析功能的 全部代码

    这么短的代码,为什么能有如此强大的功能?

    这是因为它背后使用的一个软件包,叫做 streamlit

    下面我通过实际操作,带你初步领略一下 streamlit 的威力。

    首先请你安装 Anaconda ,这个请参考我为你做的视频教程《 如何安装 Python 运行环境 Anaconda?

    然后,你需要打开终端,执行:

    pip install streamlit

    你可以创建一个新目录。然后在目录下新建一个 helloworld.py 文件,并且用任意编辑器打开它。

    我这里用 Visual Studio Code 编辑器,来编辑和制作 Python 脚本文件。

    然后,回到终端下,执行:

    streamlit run helloworld.py

    如果一切顺利,你就会看到如下图的提示。

    一般来说,你的浏览器会自动开启,并且访问上图中红色标识出的网址。

    如果浏览器没有自动开启,你手动开启一个,并且输入上述网址即可。

    为了演示方便,我这里把 Visual Studio Code 编辑器缩小到屏幕左侧半部;右边放置 Chrome 浏览器,来显示 Web 应用效果。

    我们可以开始尝试了。

    首先在 helloworld.py 中输入这些内容:

    import streamlit as st
    import numpy as np
    import pandas as pd

    st.title("my first app")

    输入完之后,你不需要去找什么执行按钮。只需要保存一下你对 helloworld.py 文件的修改即可。

    之后你会立即在右侧看到 Web 应用的运行效果。

    这里前几行语句,只是引入了几个软件包,然后设置了一下标题。

    下面我们尝试点儿好玩儿的。

    x = st.slider("x")
    y = x + 3
    y

    这时候网页上出现了滑动条,告诉你这是 x 的取值。

    我们定义了一个式子,让 y 总比 x 大 3 ,并且显示 y 。

    你可以试试,在滑动条拖拽 x 的效果。

    Jan-14-2020-18-39-15.gif
    Jan-14-2020-18-39-15.gif

    y 值紧随你的拖动变化,对吧?

    从这个简单的例子里,你可以看到 streamlit 响应用户的输入和输出是多么方便。

    而且应用上的控件一直运行。你输入的变化,会实时带来输出的变化。

    下面我们还是步入正题吧。先注释掉刚才这三条语句,免得碍事儿。

    # x = st.slider("x")
    # y = x + 3
    # y

    我们定义一个函数:

    @st.cache
    def load_data():
        df = pd.read_csv("data.csv")
        df = df
        df.columns = ['event_type', 'time', 'county', 'lat', 'lon']
        return df

    如果你学过那篇《 如何用 Python 和 Pandas 分析犯罪记录开放数据? 》,里面的其他语句你应该都认得。无非就是 Pandas 读入我们的 CSV 数据之后,取其中的 5 个列,包括:

  • EVENT_TYPE : 事件类型;
  • CREATE_TIME : 事件创建时间;
  • COUNTY :事件发生位置所在郡名称;
  • LAT :事件发生位置的纬度;
  • LON :事件发生位置的经度
  • 然后,我们把这几个列分别用小写的名称来命名。

    值得一提的,是 @st.cache ,这是一个新玩意儿。

    它是什么呢?

    这在 Python 里面,叫做装饰器(decorator) 。其实这里没有什么魔法,它只是 streamlit 软件包里,一个预先定义的函数。

    只不过这样写,相当于是你在自己的 load_data() 函数之外,又包裹了一个 st.cache() 函数的功能。每次执行的时候, st.cache() 都会参与进来。

    st.cache() 这个函数做什么用呢?

    那作用可太大了。

    因为你每次更新代码,或者用户更新输入,整个儿 Python 脚本都相当于被重新执行了一遍。

    st.cache() 装饰器可以告诉 Python :

    查查看,我包裹的这个函数,内容或者输入改过没有?如果没有,就用已存储的上次调用结果好了,别再费事重新执行一遍了。

    我们这里是从一个外部文件读入数据。就这样一个 300MB 的文件,每次读起来也得花上近 10 秒钟。更别说是那些上 GB 规模,甚至更大的文件了。

    所以,如果 Streamlit 能够帮助我们跳过一些无意义的重复操作,将节省大量的用户等待时长。

    不过这一步,你也看到了,输出没有变化。

    因为我们什么也没有输出啊。

    下面我们让 Python 实际读数据,并且把读后的数据框前 5 行用列表形式( st.table() )展示给用户。

    这一读数据不要紧,右上角会出现一个小人儿,做各种健身运动。

    这就是告诉我们,程序在忙着呢。

    忙完之后,这是结果:

    下面我们要让程序给用户选项,首先是选择观察哪一种事件类型。

    event_list = df["event_type"].unique()

    event_type = st.sidebar.selectbox(
        "Which kind of event do you want to explore?",
        event_list
    )

    解释一下,第一句是在 event_type 里面寻找全部事件类型列表。

    下面一段,采用了 st.sidebar.selectbox() 构造了一个左边栏里的下拉选择框。里面两个参数,第一个是显示给用户的提示语句,第二个,是选择列表内容。

    问题是,我们存储了之后,好像什么也没有发生啊。

    没关系,看到上图里面红色标出的这个箭头没有?

    点击它,选项就出现了。

    照葫芦画瓢,我们顺便把事件发生所在郡的下拉选择框一并做出来。

    county_list = df["county"].unique()

    county_name = st.sidebar.selectbox(
        "Which county?",
        county_list
    )

    这是效果:

    然后,我们根据用户的输入做出反应,提示给用户经过他的选择,现在符合要求的行数还有多少。

    part_df = df[(df["event_type"]==event_type) & (df['county']==county_name)]
    st.write(f"根据你的筛选,数据包含{len(part_df)}行")

    第一句里面用了个联合筛选,必须同时满足两个条件的数据,才会被保留在结果 part_df 中。

    然后,我们把一个格式化后的字符串,用 st.write() 直接输出在网页上。

    运行结果如下图所示。

    Jan-14-2020-19-04-42.gif
    Jan-14-2020-19-04-42.gif

    好了,下面可能是你最关心的一刻了。

    老师,别卖关子了,那张标示了事件位置的叠层地图怎么画啊?一共都没有多少行语句,你都讲了这么多了,怎么还没讲到?

    请你输入下面这 一行 语句:

    st.map(part_df)

    然后保存。你就会看到下面的效果了。

    是不是很惊讶?

    我第一次用的时候,也是这感觉。

    在 HackNTX 2018 编程马拉松竞赛中,我曾经找不同的编程高手学了若干种地理信息可视化的工具。每一种都得花上很多时间学习演练。

    没想到,短短一年的时间,这样的功能居然可以用一行代码就实现了。

    还是集成在 Web 应用里,可以发布给全球用户与合作者,进行展示。

    不是我不明白,这世界变化快啊。

    我知道,你又开始着急了。

    老师,这么好的东西,我可不想在本地一个人玩儿。我也想把结果发布到网络上,让别人看到我的成果。快告诉我怎么办!

    咱们 部署 ( deploy )一下它就行。

    虽然你写了半天,只是 Python 脚本。但是 Streamlit 已经把它转换成了一个动态的 Web 应用。

    所以,只要是常见的 Web 应用发布平台,理论上你都可以用来部署你的交互式数据分析作品。

    这些平台,常见的包括:

  • Glitch
  • Heroku
  • 这列表列下去就太多了。咱们这里只介绍 Heroku ,也就是前文给你展示的,样例使用的部署平台。

    这东西的好处,就是基础款 免费

    对咱们今天的教程来说,基础款就足够了。

    你需要先到 Heroku 平台 注册一个账号

    之后, 注册一个应用

    我这里起的名字,叫做 helloworld-streamlit

    你可以根据自己的喜好,起名称。

    之后我们就要部署了。

    部署的步骤,在上图中,你可以参考。

    注意,上图中,右上角的 Open App 按钮,就是你的应用链接地址,你可以把它记下来。

    首先你需要准备一些配置文件。

    全部的配置文件,我都给你展示在了前文介绍过的 这个 github 项目 中,你可以下载回来复用。

    这里需要说明的是,几个不同配置文件的用途。

    setup.sh 做一些初始设置,设定一些参数。

    注意你将来用的时候,需要把其中标红的部分, 替换成自己注册 heroku 时候的邮箱

    requirements.txt 告诉机器,需要安装哪些 Python 依赖包。

    显然,教程这里需要的依赖包不多。

    Procfile 是远端服务器上, Web 应用启动的时候,需要调用的脚本。其实里面只有一行。

    请你下载,或者自行编辑上述 3 个文件后,与你的 Python 文件放在一个文件夹下面。

    之后,请你到 这里 下载 heroku cli package。

    下载后,根据提示安装即可。

    进入终端。用 cd 命令切换到你的工作文件夹,也就是包含了你的 Python 脚本的目录。

    heroku login

    因为你已经在 setup.sh 中指定了自己的邮箱,所以这里会尝试直接用它来登录。

    这时按任意键,会跳出一个浏览器窗口。

    在浏览器中,点击确认即可登录。

    看到上面的提示,证明登录成功了。

    下面我们来设置 git ,这是推送我们文件和更新改动的途径。

    在终端下执行:

    git init

    之后设置一下与远端的 heroku 服务器的连接:

    heroku git:remote -a helloworld-streamlit

    若是看到下图,证明成功了:

    然后执行:

    git add .
    git commit -m "init"
    git push heroku master

    这样就可以把全部内容推送到 heroku 了。

    推送的第一步,是上传文件。

    Heroku 发现咱们推送的是一个 Python App ,所以自动执行许多安装设置工作。

    这些安装和配置做完后,会出现下面这样的提示。

    到这里,你的 Web 应用部署就搞定了。

    回到浏览器里,用下图中标红的这个按钮开启你自己的应用吧。

    很有成就感吧?

    尝试过之后,你应该不难发现,Streamlit 给你带来了什么。

    如果你学过 Javascript 和 Flask, Django 等 Web 应用开发技术,Streamlit 可以加快你的 Web 应用开发与测试进程。

    如果你还没有学过上述技术, Streamlit 就可以给你赋能,让你一下子有了把数据分析结果 变成产品 的能力。

    给你讲点儿更激进的。

    有人已经希望能用它替代掉 Flask 用于产品发布了。

    还有人说,将来写技术文档,也应该充分使用 Streamlit 。

    甚至,还把它比作了数据科学界的 iPhone 。

    这里,它是借喻 iPhone 开启智能手机时代,说明 Streamlit 的 划时代性

    不希望 你也变得如此激进。

    因为这里提到的每一种功用,现在还都有非常专业的工具做的更好,而且新的工具也在不断涌现。

    例如说,我们在 多个教程 中一直使用 Jupyter Notebook 。

    现在凭借 Voila 扩展的加持,你也可以很轻松地把 Jupyter Notebook 变成 Web app ,而且可以 免费运行在 mybinder 上面

    但是,你可以看到,一个新的工具,以一种简单,而不是更繁复的办法,解决一个功能痛点,是一件多么令人欣喜的事儿。

    看了这篇文章,可能会给你一种误解,似乎 JavaScript 为代表的前端编程技术,再也不需要学了。

    其实不是这样的。

    可以想象,开发门槛降低以后,将来会有更多的人使用 Python 来做 Web 应用。

    用 Streamlit 这样的方法,他们只是开发出了一个原型。

    要是想打造精品,就必须精细调控很多细节。

    这时候, Javascript 是绕不过去的。

    如果你精通 Javascript ,那你潜在的合作对象一下子就多了起来,你掌握的这门技术,也就有了更大的价值。

    还记得吗?我不止一次给你强调过, 协作网络更重要 。忘了的话,记得复习《 学 Python ,能提升你的竞争力吗? 》。

    这就好像印刷术的发明,不是让会写字这件事儿变得失去价值,而是全社会都增大了对好作品的渴求。深刻的思考,加上有效的文字表达,会让你生存得更好。

    当然,如果你不希望精通写作技艺,只是想做一个抄书匠糊口。那么印刷术就可能会替代你的工作,结果就不那么美妙了。

    本文我为你介绍了 Streamlit ,它可以让你用 Python 脚本编写简洁实用的交互式 Web 应用。

    通过学习本文,希望你掌握了以下知识点:

  • 现在你有了一种选择,仅用纯 Python 做一个完整的交互式数据分析产品出来;
  • 如何在读取数据等常用重复操作中,使用 st.cache 装饰器提升速度与效率;
  • 如何使用滑动条、下拉框等基本组件;
  • 如何在网页上输出文字、表格和图像;
  • 如何把你本地构建和测试后的 Web 应用部署到 Heroku 上,以发布给你的合作者与客户。
  • 咱们是以数据分析和可视化为例,进行了讲解。而且为了讲解的清晰,我们只介绍了 Streamlit 可实现功能的一小部分。但请注意,即便是目前, Streamlit 能帮你达成的目标,也 远远不止于此

    希望你能够举一反三,用 Streamlit 做出令人惊艳的作品。也欢迎你把作品的链接在留言区分享给咱们的同学。

    祝编程愉快!

    读过本文,如果觉得有收获,请 点赞

    要读更多的文章,微信关注我的公众号 “玉树芝兰”(nkwangshuyi) 。别忘了 加星标 ,以免错过新推送提示。

    如果本文对你身边的亲友有帮助,也欢迎你把本文通过微博或朋友圈分享给他们。

    你可能也会对以下话题感兴趣。点击链接就可以查看。

  • 如何高效学 Python ?
  • 如何用 iPad 运行 Python 代码?
  • 论文读不懂怎么办?
  • 如何不写 SQL ,探索和分析数据库?
  • 题图: Photo by Luke Chesser on Unsplash


    41
    11
    41
    等 41 人为本文章充电