Matplotlib 教程 - 了解如何使用 Matplotlib 和 InfluxDB 可视化时间序列数据

导航到

本文由 Armstrong Asenavi 撰写。向下滚动查看作者简介。

时间序列 是按时间顺序排列且在时间上均匀间隔的数据点(观测值)序列。 时间序列数据 的一些著名示例包括股票价格、年度降雨记录或每日使用自行车共享应用程序的客户数量。时间序列数据表现出某些模式,例如酒店价格根据季节的高峰和低谷。

InfluxDB 是领先的高性能 时间序列数据库 (TSDB),使开发人员能够使用时间序列数据构建实时分析、物联网和云应用程序。

在本文中,您将学习如何利用 InfluxDB 的功能以及 Matplotlib 的灵活性和强大功能,以高效地 可视化时间序列数据

什么是 InfluxDB?

InfluxDB 是一个开源的非关系型 TSDB,针对高可用性和用 Golang 编程语言编写的时间序列数据的快速读写功能进行了优化。更快的检索和存储使其在许多应用中广受欢迎,例如生产中监控应用程序、存储来自物联网传感器的数据以及执行实时分析。 InfluxDB 提供了广泛的访问选项,包括类似 SQL 的查询。

InfluxDB 非常适合存储一旦到达数据库就需要快速处理的数据。因此,它利用 网络时间协议 (NTP) 在系统之间同步时间。它还使用简单的索引方法,与其他 TSDB 相比,具有明显的速度优势。

InfluxDB 适用于所有涉及大量时间戳数据的应用程序。以下是企业如何将 InfluxDB 用于各种目的的一些示例

  • 监控生产线中的信号。 德州仪器 (TI) 使用 InfluxDB 来监控制造运营并在异常变得代价高昂之前检测到它们。 TI 监控一千多个可能成为麻烦的潜在问题信号。目标是构建可以识别关键问题并自主行动的应用程序。

  • 提高工业物联网 (IIoT) 中的连接效率。 ThingWorx Kepware 使用 InfluxDB 来帮助公司将其遗留资产连接到数据库(本地和云端)。公司可以轻松且大规模地收集和存储标签数据,从而使管理人员能够实时监控多个设备上的事件。

  • 实时监控用户统计信息。 Index Exchange 使用 InfluxDB 来监控用户统计信息。 InfluxDB 集群触发器允许实时存储数据,分析师可以经济高效地实时访问和处理这些数据。

使用 Matplotlib 和 InfluxDB 可视化时间序列数据

现在让我们仔细看看如何使用 Matplotlib 和 InfluxDB 可视化时间序列数据。您将了解 Matplotlib 的基础知识并回顾一些示例图表,然后逐步完成一个教程,该教程将向您展示如何设置和使用 InfluxDB Python 客户端来执行 CRUD 操作。

Matplotlib 简介

Matplotlib 是一个用于将数据可视化为图表、绘图和图形的开源库。它可以说是 Python 最流行的绘图库,世界各地的数据科学家和机器学习工程师都在使用它。

在 Matplotlib 中,绘图是分层的,嵌套 Python 对象以创建树状结构。一个 figure 对象封装了每个绘图,如图所示

Matplotlib figure structure

这个“figure”是可视化的顶层容器。它可以有多个轴,这些轴基本上是容器内的单独绘图。

Matplotlib 使用一个名为 pyplot 的 API,使用户更容易创建可视化效果——您不必显式配置 figureaxes 本身。

您还可以找到控制轴、刻度线、图例、标题、文本框、网格和许多其他内容的 Python 对象,所有这些都可以自定义。

Matplotlib 绘图的解剖结构如下

Matplotlib-Figure-parts

图片由 The Data Visualization Workshop 提供

可以使用 pipconda 包管理器安装 Matplotlib,具体取决于您的偏好

pip install matplotlib

conda install matplotlib

然后按如下方式安装 Numpy 模块

pip install numpy

使用别名 plt 来引用导入的子模块也很方便

import matplotlib.pyplot as plt

import numpy as np # for creating arrays

import pandas as pd # for manipulating dataframes

使用 Matplotlib,您可以创建各种可视化效果,例如条形图、饼图、雷达图、直方图和散点图。以下是一些示例,展示了如何创建一些基本图表类型

折线图

plt.plot([1, 2, 3], label='Label 1')

plt.plot([2, 4, 3], label='Label 2')

# Add title

plt.title('Two-way line plot')

plt.legend()

plt.show()

Line Plot in Matplotlib

散点图

# Create a Figure with dpi set to 100

plt.figure(dpi=100)

# Fixing random state for reproducibility

np.random. seed(100)

n = 20

x = np.random.rand(n)

y = np.random.rand(n)

colors = np.random.rand(n)

area = (30 * np.random.rand(n))**2

plt.scatter(x, y, s=area, c=colors, alpha=0.5)

# Add title

plt.title('Scatter plot')

plt.show()

Scatter-plot-in-Matplotlib

条形图

labels = ['A', 'B', 'C', 'D']

x = np.arange(len(labels))

width = 0.4

plt.bar(x - width / 2, [20, 25, 40, 10], width=width)

plt.bar(x + width / 2, [30, 15, 30, 20], width=width)

# Ticks and tick labels must be set manually

plt.xticks(x)

ax = plt.gca()

ax.set_xticklabels(labels)

# Add axes and titles

ax.set_xlabel("x-axis")

ax.set_ylabel("y-axis")

plt.title('Bar chart')

# Show plot

plt.show()

Bar chart in Matplotlib

饼图

# Create figure

plt.figure(figsize=(8, 8), dpi=100)

plt.pie([19.5, 12.2, 4.9, 3.7], explode=(0.1, 0, 0, 0), \

labels=['USA', 'China', 'Japan', 'Germany'], autopct='%.0f%%')

# Add title

plt.title('Top 4 Global Economies by GDP')

# Show plot

plt.show()

Pie-chart-in-Matplotlib

设置 InfluxDB

现在让我们深入了解本教程的细节,本教程将重点介绍云版本的 InfluxDB。由于有各种用于收集、评估和可视化数据的模块,因此入门非常容易。

首先,在 InfluxDB Cloud 网站上注册为免费用户。务必单击发送到您电子邮件的链接来验证您的帐户。然后登录并选择云提供商(AWS、Azure 或 GCP)。请注意,免费版本提供有限的读取和写入,最多 10,000 个数据集,以及 30 天的保留策略。

注册后,您应该会看到仪表板页面

InfluxDB UI

接下来,导航到 Buckets 部分并创建一个存储桶

Creating a bucket in influxDB

导航到 API Token 部分并创建一个 All Access API Token。这很重要,因为您将数据写入存储桶; All Access Token 将允许您无限制地读取和写入数据到存储桶中。

然后,您需要创建所需的文件夹,设置 Python 虚拟环境,并安装所需的软件包

# Create a directory

mkdir influxDB-Tutorial

# Navigate into the folder

cd influxDB-Tutorial

接下来,使用 venv 库创建一个虚拟环境。请注意,当运行 Python v3.6+ 时,建议使用 venv。有关更多信息,请参阅 此文档

# To create a virtual environment

pip install venv

# Activate virtual environment

source venv/Scripts/activate

# Install influxDB client

pip install influxdb-client

# Create a file known as named __init__.py

touch __init__.py

# Create a file known a file .env to store credentials

touch .env

# Create .gitignore file to prevent .env going public

touch .gitignore

# Install python-dotenv to allow access to the .env file

pip install python-dotenv

# Create folders for storing data and img

mkdir data

mkdir img

# Install yfinance to Collect data

pip install yfinance

# Install matplotlib

pip install matplotlib

将您的凭据(令牌、存储桶和组织)存储在 .env 文件中。请记住将 .env 文件包含在 .gitignore 文件中。

INFLUX_TOKEN = " All access token from InfluxDB"

ORG = "email you registered with on InfluxDB"

BUCKET = "name of your bucket"

__init__.py 文件中,开始导入 dotenv 和 os 模块,以便从 .env 文件中读取凭据。

然后返回到 InfluxDB Cloud UI,转到 Sources 部分。在客户端库中,选择“Python”。复制 Initialize the Client 下的代码并将其粘贴到 __init__.py 文件中

Initialize the Client

# Import modules

from dotenv import load_dotenv

import os

from influxdb_client import InfluxDBClient, Point, WriteOptions

from influxdb_client.client.write_api import SYNCHRONOUS

load_dotenv()

token = os.getenv('INFLUX_TOKEN')

org = os.getenv('ORG')

bucket = os.getenv('BUCKET')

client = InfluxDBClient(url="https://us-east-1-1.aws.cloud2.influxdata.com", token=token, org=org)

接下来,运行您的 Python 文件

$ python __init__.py

如果没有错误消息,则您已成功连接到 InfluxDB Cloud。

将 Matplotlib 与 InfluxDB 结合使用

本教程使用来自 Yahoo Finance 的四家科技公司的调整后收盘价:Apple (AAPL)、Amazon (AMZN)、Google (GOOG) 和 Microsoft (MSFT),时间范围从 2020 年 1 月 1 日到 2022 年 3 月 30 日。目的是可视化 COVID-19 期间的股票价格趋势。

下载和保存数据

首先,使用 yfinance 库 下载数据

import yfinance as yf

tickers = ['AAPL', 'GOOG', 'AMZN', 'MSFT']

#Download only adjusted closing price for the tickers

data = yf.download(tickers, start="2020-01-01", end="2022-03-30")['Adj Close']

data.head()

导入的数据将如下所示

Output-table-stock-data

然后使用此代码将数据另存为 CSV 文件

# Save the data into the data folder as a csv file.

data.to_csv('data/stocks.csv')

准备写入数据

接下来,使用以下代码加载所需的库并链接到 InfluxDB Python 客户端

# Import required packages and access influxdb client

from collections import OrderedDict

from csv import DictReader

import rx

from rx import operators as ops

from dotenv import load_dotenv

import os

from influxdb_client import InfluxDBClient, Point, WriteOptions

from influxdb_client.client.write_api import SYNCHRONOUS

load_dotenv()

token = os.getenv('INFLUX_TOKEN')

org = os.getenv('ORG')

bucket = os.getenv('BUCKET')

client = InfluxDBClient(url="https://us-east-1-1.aws.cloud2.influxdata.com", token=token, org=org)

创建用于写入数据的函数

然后使用下面的代码准备点结构中的 CSV 数据,并将其写入名为 finance-bucket 的 InfluxDB 存储桶中

def parse_row(row: OrderedDict):

"""

This function parses rows into Point with structure:

the csv file has the following columns:

Date,AAPL,AMZN,GOOG,MSFT

...

:param row: row of csv file

:return: Parsed csv row to Point

"""

return Point("financial-analysis")\

.tag("type", "stock-daily") \

.field("aapl", float(row['AAPL'])) \

.field("amzn", float(row['AMZN'])) \

.field("goog", float(row['GOOG'])) \

.field("msft", float(row['MSFT'])) \

.time(row['Date'])

"""

Convert the stocks.csv into data points

"""

data = rx \

.from_iterable(DictReader(open('./data/stocks.csv', 'r'))) \

.pipe(ops.map(lambda row: parse_row(row)))

"""

Create a client that writes data.

"""

write_api = client.write_api(write_options=WriteOptions(batch_size=5_000, flush_interval=1_000))

"""

Write data into InfluxDB

"""

write_api.write(bucket=bucket, record=data)

write_api.close()

使用 Flux 从 InfluxDB Cloud 查询数据

数据进入存储桶后,您可以使用 Flux 语言查询它,并使用以下代码返回数据帧 (df)

query_with_multiple_fields ='''

from(bucket: "finance-bucket")

|> range(start:0, stop: now())

|> filter(fn: (r) => r._measurement == "financial-analysis")

'''

# Output the data as data frame named df

df = client.query_api().query_data_frame(org=org, query=query_with_multiple_fields)

df.head()

如您所见,数据帧中的数据以平面结构呈现,每一行中都有一个字段

Flux Query 1 output

编写 Flux 查询以将时间序列透视为数据帧

接下来,使用 Flux 查询并将数据 透视 到数据帧中,其中所有字段都呈现为列

query_with_pivot ='''

from(bucket: "finance-bucket")

|> range(start:0, stop: now())

|> filter(fn: (r) => r._measurement == "financial-analysis")

|> pivot(rowKey:["_time"], columnKey: ["_field"], valueColumn: "_value")

|> keep(columns:["_time", "aapl", "amzn", "goog", "msft"])

'''

# put the data in a dataframe

df = client.query_api().query_data_frame(org=org, query=query_with_pivot)

df.head()

输出显示数据现在位于预定的数据帧中。但是,正如您在下面的屏幕截图中看到的,InfluxDB 添加了“result”和“table”列,您将在下一节中删除这些列。

Flux-Query-2-output

删除不相关的列

使用 drop 方法 删除与此分析无关的“result”和“table”列

df["_time"] = pd.to_datetime(df["_time"].astype(str))

df = df.drop(columns=["result", "table"])

df = df.set_index("_time")

df.head()

最终数据帧呈现如下

Preprocessed-dataframe-for-analysis

规范化数据帧以创建专业的图表

数据帧显示 AMZN 和 GOOG 股票价格以千为单位,而 AAPL 和 MSFT 的股票价格以十和百为单位。按原样绘制数据将在顶部显示两个图表(AMZN 和 GOOG),在底部显示两个图表(MSFT 和 AAPL),这看起来不专业。为了解决这个问题,您可以将股票数据相对于第 1 天进行规范化,强制第一天的价格从 1 美元开始。

使用以下代码执行此操作

def normalize_df(df):

"""normalizes stock data w.r.t price in day 1,

force first day price to start at $1"""

return df/df.iloc[0,:]

data = normalize_df(df)

使用 Matplotlib 可视化数据

最后,使用此代码创建股票价格的时间序列图

# Create the plot

ax = data.plot(figsize=(15, 10))

ax.set_xlabel("Date")

ax.set_ylabel("Adjusted Price")

plt.title('Adjusted Closing Prices')

plt.legend(loc='upper left', fontsize=12)

plt.tight_layout()

plt.style.use('bmh')

plt.grid(True)

plt.show()

运行代码后,输出将如下所示

Time Series Plot

分析数据

正如您在最终图中看到的,在 2020 年 3 月至 4 月期间,当各国政府宣布因 COVID-19 采取封锁措施时,价格出现暂时下跌。此后,尽管受到 COVID-19 的影响,科技股的表现仍然相对良好。有许多选项可用于更深入的 时间序列数据分析,以及如何通过 时间序列预测 方法进行预测。

结论

在本教程中,您学习了 Matplotlib 中时间序列可视化的基础知识,Matplotlib 是 Python 的流行绘图库。您还学习了如何设置 InfluxDB Cloud、将数据写入存储桶以及将数据读入 Python 进行分析,使用简单的 Python 脚本在 InfluxDB 中执行读写操作。

正如您所见,结合 InfluxDB 和 Matplotlib 的功能来高效地可视化时间序列数据具有强大的功能和灵活性。您可以在 此 GitHub 存储库 中访问本教程的完整源代码。

其他资源

如果您对其他一些教程感兴趣,这些教程展示了如何使用 InfluxDB 可视化数据,请查看以下链接

  • Recharts 教程 - 了解如何使用 Recharts 图表库和 InfluxDB 可视化 IoT 数据

  • Highcharts InfluxDB 教程 - 了解如何将 Highcharts JavaScript 图表库与 InfluxDB 结合使用来可视化海洋潮汐数据。

  • React Native Victory 教程 - 本教程展示了如何使用 Victory 图表库的 React Native 版本,该版本允许您使用您的 Web 开发经验来创建原生移动应用程序。

  • Nivo 教程- 在本文中,您将了解 Nivo 图表库的基础知识,以及如何创建各种类型的图表,同时从 InfluxDB 中提取数据。

  • Plotly.js 教程- 使用 PlotlyJS 图表库显示存储在 InfluxDB 中的数据。

关于作者

Armstrong Asenavi 是一位经验丰富的机器学习工程师和数据分析师,热衷于洞察力、商业智能 (BI)、仪表板、指标、分析、建模和可视化。他在价值提升型数据工程项目的各个阶段都拥有必要的经验,并且精通主要的编程语言,包括 Python、R、JavaScript、SQL 和 DAX。他在研究、项目管理和技术报告撰写方面拥有强大的背景。他是一位分析型、批判性思维者和数据驱动型分析师。 Armstrong 沟通清晰,能够将复杂的信息转化为可行的解决方案。他与团队成员合作良好,并在团队环境中茁壮成长。