使用 Streamlit 和 InfluxDB 可视化数据
作者:社区 / 产品, 开发者
2022 年 10 月 20 日
导航至
本文由 Fortune Adekogbe 撰写。向下滚动查看作者简介和照片。
根据 Python 开发者调查 2021 结果,大多数开发者不积极使用前端工具。这意味着如果您想创建界面来显示机器学习模型和其他您构建的系统,您很可能需要另一位开发者的协助。
这就是 Streamlit(一个开源应用框架)可以作为替代方案提供帮助的地方,它使您无需费力使用前端相关工具和语言(如 HTML5、CSS、React 和 JavaScript)即可创建用户界面。从头开始构建界面,您只需要 Python 和 Streamlit API 中的预配置元素。
这比您自己构建应用程序并尝试编写少量代码来创建有用的应用程序要容易得多。此外,Python 生态系统提供的大多数优秀库仍然可供您使用。
在本文中,您将了解更多关于 Streamlit 的信息,以及它如何简化应用程序的创建过程。此外,您还将学习如何创建和设置 InfluxDB 数据库,并查询 Streamlit 应用程序的数据。
什么是 Streamlit
如前所述,Streamlit 是一个开源框架,用于完全在 Python 中构建 Web 应用程序。这使 Python 开发者、机器学习工程师、数据分析师和数据科学家无需整个软件开发团队即可开发出令人惊叹的应用程序。
这个框架背后的概念是,创建应用程序应该像在 Jupyter Notebook 中工作一样自然,但具有强大的应用程序开发框架的所有灵活性。
为了使您能够使用熟悉的语言和开发环境,Streamlit 专注于确保所有必要的脚本都可以用 Python 完成。此外,它的 API 提供了可以用来简单地通过将各种类型的微件声明为变量来实现的元素。这样做可以使代码变得有条理且简洁。
Streamlit 还具有缓存系统,该系统充当数据存储,使您能够重用昂贵的计算、下载的数据和模型等信息。这减少了延迟并加快了应用程序的速度,因为您的 Streamlit 应用程序代码会在每次用户交互时更新和重新运行。
当您更改代码时,Streamlit 具有类似于热重载的功能,使您能够立即重新加载您的应用程序。即使在开发阶段,这也可以避免延迟,因为 Streamlit 只会再次运行管道的更新部分。此外,它与 GPU 配合良好,这加快了深度学习模型的推理速度。
使用存储在 InfluxDB 中的时间序列数据实现 Streamlit
为了演示 Streamlit 的价值,在本教程中,您将构建一个简单的仪表板来可视化和分析天气数据。您将使用 InfluxDB 作为您的数据库来实现这一点,因为它专为处理时间序列数据而设计。
您可以在此GitHub 存储库的主分支中找到本教程中使用的所有代码片段。
设置 InfluxDB
首先,您需要在本地计算机上设置 InfluxDB 的开源版本作为服务器。转到 InfluxDB OSS 文档中的安装页面以开始
有关下载、安装和启动 InfluxDB 服务器的说明,请单击与您的操作系统对应的按钮。
完成后,打开您的浏览器并转到 http://localhost:8086 以确保服务器已启动。如果您使用不同的端口号,请确保在 URL 中替换它。这将加载 InfluxDB 用户界面。
要完成 InfluxDB 设置,请单击开始使用,然后输入必要的信息并选择继续。完成操作后,您将被带到主页
将数据写入 InfluxDB
设置完成后,您需要将数据写入数据库。为此,请为项目创建一个目录,并创建一个 data/
目录。在终端中运行以下命令以下载天气数据
wget -o data/jena_climate_2009_2016.csv.zip https://storage.googleapis.com/tensorflow/tf-keras-datasets/jena_climate_2009_2016.csv.zip
压缩的 CSV 文件现在应该被提取并放入 data/
目录中。虽然有几种将数据写入 InfluxDB 的方法,但您将使用 pandas.DataFrame 方法。
在继续之前,转到您的 InfluxDB 界面,单击左侧菜单中的加载数据选项,然后选择 Buckets。单击右侧的 + 创建 Bucket 按钮,命名 bucket,然后选择创建
接下来,您需要生成一个 API 令牌。在左侧菜单中,单击 API 令牌选项。选择右侧的 + 生成 API 令牌按钮,然后选择 All Access API Token。描述令牌并单击保存。
现在,在项目目录中创建一个虚拟环境并激活它,方法是执行以下命令(对于 Linux/macOS 用户,请按照 这些说明执行相同的操作)
python -m venv .venv
.venv\Scripts\activate.bat
接下来,使用 pip 安装本教程所需的每个库
pip install pandas influxdb-client matplotlib pandas python-dotenv streamlit
然后从 InfluxDB 复制 API 令牌并将其放入 env 文件中
INFLUX_TOKEN={TOKEN FROM INFLUXDB}
完成后,创建一个 Python 脚本来预处理数据并将其写入 InfluxDB
import os
import pandas as pd
import matplotlib.pyplot as plt
from influxdb_client import InfluxDBClient, WriteOptions
from dotenv import load_dotenv
load_dotenv()
df = pd.read_csv("data/jena_climate_2009_2016.csv")
df = df[['Date Time', 'T (degC)']]
df.index = pd.to_datetime(df.pop('Date Time'), format='%d.%m.%Y %H:%M:%S')
df['Measured Fluid'] = ['Air'] * df.shape[0]
plt.plot(df['T (degC)'])
plt.show()
在这里,您首先导入所有必要的模块。然后您使用之前安装的 python-dotenv
中的 load_dotenv()
方法来加载环境变量。接下来,您使用 pandas.read_csv()
方法,通过传递文件路径作为参数来读取 CSV 文件。
此数据集包含温度、压力、湿度和各种量的其他读数。为了本教程的目的,将仅与温度读数进行交互。
从数据帧中切片日期和温度列。使用 pandas.to_datetime()
方法将 'Date Time'
列转换为 DateTime
数据类型,使用 df.pop()
方法从数据帧中删除 'Date Time'
列,并将此修改后的列设置为数据帧的索引,方法是将其分配给 df.index
。
接下来,向数据帧添加一列以表示测量的流体,在本例中,它是空气,并且在每一行上都相同。之后,将温度列传递给 plt.plot
以创建绘图,并添加 plt.show()
以确保它出现。您应该看到以下图像。注释掉 plt.show()
,使其不会阻止剩余代码行的执行
以下代码行将数据帧写入 InfluxDB
ORG = "MY-ORG"
BUCKET = "MY-BUCKET"
TOKEN = os.getenv("INFLUX_TOKEN")
with InfluxDBClient(url="http://localhost:8086", token=TOKEN, org=ORG) as _client:
with _client.write_api() as _write_client:
_write_client.write(BUCKET, ORG, record=df, data_frame_measurement_name='air_temperature',
data_frame_tag_columns=['Measured Fluid'])
在之前的代码中,您创建变量以字符串形式存储您的组织和 bucket 的名称。使用 os.getenv()
方法,您定义一个不同的变量来加载 API 令牌。然后,您使用上下文管理器通过 with
语句创建 InfluxDBClient()
的实例,其参数为 InfluxDB 服务器的 URL、令牌和组织。
然后,您创建第二个上下文管理器,该管理器使用客户端实例创建 client.write_api()
实例。接下来,您调用 write_client.write()
方法,传递 bucket 和组织名称作为参数。您还将数据帧传递给 record 参数,将 'air_temperature'
传递给 data_frame_measurement_name
参数,并将 ['Measured Fluid']
传递给 data_frame_tag_columns
参数。最后,运行此脚本以将数据写入 InfluxDB。
创建 Streamlit 应用程序
下一步是查询 InfluxDB 获取数据并将其提供给您的 Streamlit 应用程序。首先,创建一个名为 app.py
的新 Python 脚本并导入必要的模块
import os
from influxdb_client import InfluxDBClient
import streamlit as st
from dotenv import load_dotenv
load_dotenv()
ORG = "MY-ORG"
BUCKET = "MY-BUCKET"
TOKEN = os.getenv("INFLUX_TOKEN")
@st.cache
def get_weather_data(time_range=20):
client = InfluxDBClient(url="http://localhost:8086", token=TOKEN, org=ORG)
query_api = client.query_api()
result_df = query_api.query_data_frame(f'from(bucket:"{BUCKET}") '
f'|> range(start: -{time_range}y) '
'|> pivot(rowKey:["_time"], columnKey: ["_field"], valueColumn: "_value") '
'|> keep(columns: ["_time","Measured Fluid", "T (degC)"])')
result_df['month'] = result_df['_time'].dt.month
client.close()
return result_df
在之前的代码示例中,导入模块后,您加载环境变量并创建变量来存储您的组织、bucket 和令牌。
然后,您定义一个函数 get_weather_data()
以从 InfluxDB 读取温度数据。应将 @st.cache
装饰器添加到此方法,以保证查询被缓存,并且不会在每次用户交互时重新运行。然后,您通过在函数中创建 InfluxDBClient
实例来创建查询 API 的实例。
使用 query_api.query_data_frame()
方法,并将查询作为其参数,以确保结果作为数据帧返回。此查询是使用 InfluxData 的 Flux 脚本语言编写的字符串。通过逐行观察它,您可以看到 bucket、要查询的时间范围(以年为单位)、pivot(确定输出行所依赖的列)以及要返回的列都已定义。在此之后,通过在 DateTime
列上调用 .dt.month
方法来创建 month 属性。
然后调用 client.close()
方法以关闭客户端并返回数据帧。
接下来定义 Streamlit 应用程序的组件。折线图、面积图和条形图是必须创建的三种图表类型
chart_df = get_weather_data()
chart_df.rename(columns={"_time": "Date-Time", "T (degC)": "Temperature (°C)"},
inplace=True)
st.title("Air Temperature (°C) vs. Time")
st.write("## Line Chart")
st.line_chart(chart_df, x="Date-Time", y="Temperature (°C)")
在此代码中,调用 get_weather_data
方法进行查询,并在数据帧中返回数据。接下来,将更具描述性的列名添加到数据帧中。然后使用 st.write()
方法指定绘图名称,并创建一个折线图以显示数据。数据帧以及 x 轴和 y 轴的列名作为参数传递给 st.line_chart()
方法以完成此操作。
在您的终端中运行命令 streamlit run app.py
以查看应用程序。这会在您的浏览器中启动一个选项卡,其视图类似于此处显示的视图
正如您所看到的,与之前使用 matplotlib
创建的绘图不同,Streamlit 绘图是交互式的。通过将光标移动到绘图上方,您可以看到有关每个数据点的更多信息。此外,您可以放大以查看更具体的时间范围。
然后制作第二和第三个绘图,如此处所示
st.write("## Area Chart")
st.area_chart(chart_df, x="Date-Time", y="Temperature (°C)")
chart_month = chart_df.groupby('month')['Temperature (°C)'].mean()
st.write("## Bar Chart\nThis shows the average temperature in each month")
st.bar_chart({'Month number': chart_month.index,
'Average Temperature (°C)': chart_month.values},
x="Month number",
y="Average Temperature (°C)")
然后添加第二个绘图的标题,并使用 st.area_chart()
以类似的方式制作面积图。
使用 dataframe.groupby()
方法按月份对数据进行分组,并确定平均温度,以便创建第三个图表。
最后,添加第三个绘图的标题,然后使用 st.bar_chart()
方法创建图表。数据被解析为月份编号和每个月份的平均温度的字典。
要查看应用程序,请导航到您的浏览器并单击右上角的重新运行按钮。以下绘图将添加到您的仪表板
与之前类似,这些绘图也是交互式的,并为您提供了一种与数据交互并在部署后与他人共享数据的绝佳方式。您可以在此GitHub 存储库的主分支中找到此处使用的所有代码片段。
结论
在本文中,您了解了 Streamlit、它的优点以及它的功能。您还可以设置 InfluxDB 数据库、向其写入数据并从中读取数据。此外,您可以使用 Streamlit 构建仪表板来可视化数据。
InfluxDB 由 InfluxData 开发,旨在促进实时应用程序的创建和时间序列数据的处理。您可以使用 InfluxDB 创建一个系统来跟踪和分析来自您的网络或传感器的实时数据。注册并立即开始使用 InfluxDB。
附加资源
如果您有兴趣了解更多关于数据可视化或使用时间序列数据的信息,请查看以下资源
关于作者
Fortune 是 Josplay 的 Python 开发者,擅长处理数据和构建智能系统。他也是一名工艺工程师和技术作家。