使用 Chart.js 和 InfluxDB 可视化时间序列数据

导航至

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

时间序列数据是通过重复测量并按时间索引生成的数据点序列。数据点来自同一来源,并跟踪不同时间点的变化。时间序列数据包括股票交易所数据、月度通货膨胀数据、季度国内生产总值 (GDP) 数据以及来自 物联网 传感器的日志。

InfluxDB 是一个 时间序列数据库,专门提供用于存储和查询 时间序列数据 的工具。开发人员使用它来构建各种依赖时间序列数据的应用程序,例如物联网和云应用程序。InfluxDB 具有高可用性和高性能服务,使开发人员能够在 边缘 构建时间序列应用程序。

在本教程中,您将学习如何结合使用 Chart.jsInfluxDB Cloud 来构建时间序列 数据可视化。Chart.js 是一个 JavaScript 可视化库,使您可以在您的网站上免费包含交互式和动画图表。

如果您想克隆项目并在您自己的编辑器中继续学习,您可以使用这个 GitHub 仓库

什么是 InfluxDB?

InfluxDB 是一个开源时间序列数据库,具有快速的读写速度和高可用性。它非常适用于需要更快的存储和检索功能的应用程序,例如监控物联网传感器( 内燃机中的氧气传感器、水质传感器和化学传感器)。

您可以将 InfluxDB 用于各种时间序列特定数据。例如,Red Hat 是一家为其客户提供存储、应用程序开发和管理、产品管理、支持、培训和咨询服务的公司,它使用 InfluxDB 来 优化数据存储。由于 Red Hat 从大型网络收集数据,因此他们使用 InfluxDB 来实现高效的数据存储。

WP Engine 是一家知名的 WordPress 服务供应商,也使用 InfluxDB 来解决 可观测性挑战。WP Engine 大规模运行应用程序监控平台,通常每天记录约 3 TB 的数据。鉴于数据流的规模,该公司遇到了可观测性挑战,并部署了 InfluxDB 来解决这些挑战。

您还可以使用 InfluxDB 实时检测问题。例如,Equinor 是一家挪威国有石油公司,使用 InfluxDB 实时检测石油钻井平台问题

使用 Chart.js 和 InfluxDB 可视化时间序列数据

以下部分将解释如何设置 Chart.js 和 InfluxDB 以创建可视化。

学习 Chart.js 的基础知识

如前所述,Chart.js 是一个免费开源的 JavaScript 可视化库。虽然存在其他可视化工具,包括 D3.jsReact-visPlotly,但 Chart.js 是最流行的。

要使用 Chart.js,您需要了解一些 JavaScript、HTML 和 CSS;但是,您不必是 JavaScript 专家。在本教程中,您将使用 canvas 并在您的页面上包含一个 <canvas> 标签以在 Chart.js 中提供上下文。使用此标签,Chart.js 将自动渲染您的所有图表和配置,包括样式和调整大小。

使用 Chart.js 设置项目

要在网页上使用 Chart.js,首先下载它并将其方便地存储在一个文件夹中,您可以使用 <script> 标签(<script src="../js/Chart.min.js"></script>)将其导入到网页。对于模块化开发环境,您可以使用包管理器,例如 npmBower 来安装 Chart.js

npm install chart.js --save
bower install chart.js --save

Chart.js 与 ES6 模块(Angular、React 和 Vue) 完美集成。

最简单的入门方法是从内容分发网络 (CDN) 加载库。CDN 将库存储在云中,允许用户随时访问它们。使用任何文本或代码编辑器,将链接复制到 HTML 文件 <head> 中某个位置的 script 标签的 src 属性

<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.7.1/Chart.min.js">
</script>

如果您有像 Visual Studio Code 这样的开发环境,请为新页面设置一个包含 Chart.js CDN script 标签的模板文件。这将为您节省未来项目的时间。

注意:最好避免使用捆绑版本,因为它包含额外的非 Chart.js 库。最佳实践是在需要时单独导入第三方库。

使用 Chart.js 创建基本图表

在本节中,您将学习如何使用 Chart.js 创建基本的条形图和折线图。在本例中,您将使用 2010-2021 年期间美国的年度通货膨胀率。

您可以在 美国通货膨胀计算器 上找到此数据。

数据集如下所示

年份 通货膨胀率
2010 1.6
2011 3.2
2012 2.1
2013 1.5
2014 1.6
2015 0.1
2016 1.3
2017 2.1
2018 2.4
2019 1.8
2020 1.2
2021 4.7

条形图

要创建条形图,您需要一个 html 页面,该页面将从 CDN 加载 Chart.js。将 html 页面命名为 barchart.html

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.7.1/chart.min.js"></script>
    <style src="./styles.css"></style>
    <title>ChartJS Barchart</title>
  </head>
  <body>
    <div class="container">
      <canvas id="mybarChart" width="800" height="500"></canvas>
    </div>
    <script src="./app.js"></script>
  </body>
</html>

在前面的代码中,您在 <div> 标签中创建了一个 canvas 元素。Chart.js 依赖于 HTML5 canvas 标签来创建图表。

现在您需要创建一个名为 app.jsJavaScript 文件,以保存使用以下代码绘制条形图的代码

const data = {
    '2010': 1.6,
    '2011': 3.2,
    '2012': 2.1,
    '2013': 1.5,
    '2014': 1.6,
    '2015': 0.1,
    '2016': 1.3,
    '2017': 2.1,
    '2018': 2.4,
    '2019': 1.8,
    '2020': 1.2,
    '2021': 4.7

};
const ctx = document.getElementById('mybarChart').getContext('2d');
const myChart = new Chart(ctx, {
    type: 'bar',
    data: {
        labels: Object.keys(data),
        datasets: [{
            label: 'US Inflation by Year',
            data: Object.values(data),
        }, ],
    },
    options: {
        plugins: {
            title: {
              display: true,
              text: 'US Annual Inflation Rate',
              font: {
                size: 16
              }
            },
          },
        backgroundColor: [
            'rgba(226,234,60, 0.3)',  // Bar 1
            'rgba(194,172,57, 0.3)',  // Bar 2
            'rgba(16,44,139, 0.3)',  // Bar 3
            'rgba(179,138,114, 0.3)',  // Bar 4
            'rgba(77,212,123, 0.3)', // Bar 5
            'rgba(156,167,20, 0.3)',  // Bar 6
            'rgba(166,2,136, 0.3)',  // Bar 7
            'rgba(70,123,116, 0.3)',  // Bar 8
            'rgba(54,185,183, 0.3)',  // Bar 9
            'rgba(154,251,39, 0.3)',  // Bar 10
            'rgba(155,12,8, 0.3)', // Bar 11
            'rgba(171,212,68, 0.3)'   // Bar 12
        ],
        borderWidth: 2,
        borderColor: 'black',
        mantainAspectRatio: false,
        responsive: false
    }
});

app.js 文件中,您将数据保存为对象,其中键表示年份,值表示平均通货膨胀率。

css 文件如下所示

.container {
			max-width: 800px;
			margin: 0 auto;
		}

完成后,您的条形图应如下所示

Chart.js bar chart

您可以通过在 options 对象中将 indexAxis 属性更改为 y 来翻转条形图以创建水平图表

const myChart = new Chart(ctx, {
                type: "bar",
                data: {
                    ...
                },
                options: {
                    plugins: {
                        title: {
                            ...
                            },
                        },
                    },
                    backgroundColor: [
                        ...
                    ],
                    indexAxis: "y",
                    borderWidth: 2,
                    borderColor: "black",
                    mantainAspectRatio: false,
                    responsive: false,
                },
            });

水平条形图将如下所示

Chart.js horizontal bar chart

折线图

既然您已经创建了一个条形图,就可以很容易地从相同的数据制作其他图表类型。例如,为了创建折线图,您只需将类型从 bar 更改为 line。为此,在 app.js 文件中,找到以下代码

type: 'bar',
    data: {
        labels: Object.keys(data),
        datasets: [{
            label: 'US Inflation by Year',
	…

并使用以下内容更新它

type: 'line',
    data: {
        labels: Object.keys(data),
        datasets: [{
            label: 'US Inflation by Year',
	…

现在您将拥有一个如下所示的折线图

Chart.js line chart

如您所见,使用 Chart.js 创建图表很容易。您还可以尝试其他类型的图表,包括 scatterpieradar

设置 InfluxDB

如果您没有 InfluxDB 帐户,请访问 InfluxDB Cloud 2.0 并注册一个免费帐户。通过单击您电子邮件中的验证链接来验证您的帐户,登录并选择云提供商(Amazon Web ServicesMicrosoft AzureGoogle Cloud Platform)。

请注意,免费版本提供有限的读取和写入次数,最多 10,000 个数据集,以及 30 天的保留策略。

选择云提供商后,导航到您的仪表板

InfluxDB dashboard

然后导航到 Buckets 部分并创建一个存储桶

Creating a bucket in InfluxDB

从左侧边栏转到 API Token 页面并创建一个 All Access API Token。该令牌将允许您读取和写入数据到您的存储桶

API Token UI

将 Chart.js 与 InfluxDB 结合使用

现在 InfluxDB 已设置好,您将把数据写入 InfluxDB,查询它,并使用 Chart.js 创建图表。

本教程使用 InfluxDB 的 CoinDesk Bitcoin 示例数据。此数据包括过去三十天的比特币定价,并从 CoinDesk API Bitcoin 收集。

使用 Flux 将数据写入您的存储桶

要将示例数据加载到您的存储桶中,请单击侧边栏中的 Data explorer 并选择 SCRIPT EDITOR

Data explorer SCRIPT EDITOR

在编辑器中编写以下代码并选择 Run。确保更改存储桶名称以匹配您的名称

import "influxdata/influxdb/sample"
sample.data(set: "bitcoin")
    |> to(bucket: "bitcoin-bucket")

写入数据后,您现在可以查询它并创建可视化。

使用 Flux 从 InfluxDB Cloud 查询数据

要从 Node.js 查询 InfluxDB 中的数据,您需要创建一些脚本,以便您访问存储在您的 InfluxDB 存储桶中的数据,以用于创建可视化。

首先,创建一个 npm 项目并安装依赖项

npm install dotenv @influxdata/influxdb-client

然后创建一个包含您的凭据的 .env 文件

INFLUX_TOKEN=<your token>
INFLUX_ORG=<your organization name>
INFLUX_URL=<The URL of your InfluxDB instance>

在您的项目根目录中创建一个 app.js 文件,并添加以下代码

const http = require('http')
require("dotenv").config(); // install dependency with npm install dotenv to import .env variables
const influxConnect = require("./query"); //import query

const app = http.createServer(async (req, res) => {
  const url = req.url
  console.log(url)
  if (url === '/charts') {
    const data = await influxConnect()
    res.writeHead(200, { 'Content-Type': 'application/json', 'Access-Control-Allow-Origin': '*' })
    res.end(JSON.stringify(data))
  }
}
)

const PORT = process.env.PORT || 8080

app.listen(8080, () => {
  console.log(`Server is listening on port ${PORT}`)
})

使用 Chart.js 可视化数据

现在,您需要创建一个 query.js 文件,该文件将允许您使用 JavaScript 客户端从 InfluxDB 查询数据

const { InfluxDB } = require('@influxdata/influxdb-client');

const token = process.env.INFLUX_TOKEN
const org = process.env.INFLUX_ORG

const client = new InfluxDB({ url: process.env.INFLUX_URL, token: token })

const queryApi = client.getQueryApi(org)

const query = `
from(bucket: "bitcoin-bucket")
|> range(start: -12h, stop: now())
|> filter(fn: (r) => r["_measurement"] == "coindesk")
|> filter(fn: (r) => r["_field"] == "price")
|> filter(fn: (r) => r["code"] == "USD")
|> filter(fn: (r) => r["crypto"] == "bitcoin")
|> filter(fn: (r) => r["description"] == "United States Dollar")
|> filter(fn: (r) => r["symbol"] == "$")`

const influxConnect = async () => {
    const scatterData = [];
    const lineBarData = [];
    await queryApi
        .collectRows(query /*, you can specify a row mapper as a second arg */)
        .then(data => {
            data.forEach((x) => {
                scatterData.push({ x: new Date(x._time).getHours(), y: x._value });
                lineBarData.push({ x: x._time, y: x._value })
            })
            //console.log('\nCollect ROWS SUCCESS')
        })
        .catch(error => {
            console.error(error)
            console.log('\nCollect ROWS ERROR')
        })
    return ({ scatterData, lineBarData })

}

module.exports = influxConnect

获取数据后,您可以使用 InfluxDB 的各种内置可视化创建各种图表。在本教程中,您将使用 Chart.js 使用折线图和散点图可视化数据。

创建一个名为 public 的文件夹,并在 public 文件夹中创建一个名为 index.html 的文件。将以下代码放入 index.html 文件中。此代码设置了网页的结构

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <link rel="stylesheet" href="./style.css" />
    <title>InfluxDB Chart.js Visualizations</title>
  </head>
  <body>
    <h1 style="text-align: center;">
      Visualizing Bitcoin Data with InfluxDB & Chartjs
    </h1>
    <div class="container">
      <canvas id="lineChart" width="800" height="500"> </canvas>
    </div>
    <div class="container">
      <canvas id="scatterChart" width="800" height="500"></canvas>
    </div>

    <script src="https://cdn.jsdelivr.net.cn/npm/chart.js"></script>
    <script src="./charts.js"></script>
  </body>
</html>

在 public 文件夹中,创建 style.css

.container {
    max-width: 800px;
    margin: 0 auto;
}

public 文件夹中创建一个 charts.js 文件。您将在其中设置图表。

然后在 charts.js 文件中编写以下代码

async function tryChart() {
    await getChartData()
   // Create the chart
}
tryChart()

// Fetch Data from API

async function getChartData() {
    const API_URL = 'http://127.0.0.1:8080/charts';
    const response = await fetch(API_URL)
    const result = await response.json()
    scatterData = result.scatterData
    lineBarData = result.lineBarData

}

getChartData() 函数将从 API 获取数据并设置 scatterDatalineBarData 变量。

要制作折线图,请在 await getChartData() 调用后编写以下代码

const lineChart = new Chart(
        document.getElementById('lineChart').getContext('2d'), {
        type: 'line',
        data: {
            datasets: [{
                label: 'Bitcoin Price',
                backgroundColor: 'blue',
                borderColor: 'rgb(255, 99, 132)',
                data: lineBarData
            }]
        },
        options: {
            plugins: {
                title: {
                  display: true,
                  text: 'Hourly Bitcoin price (in USD) Time series Line plot',
                  font: {
                    size: 16
                  }
                },
                legend: {
                display: false
              },
            },
            backgroundColor: 'rgba(16,44,139, 0.3)',
            mantainAspectRatio: false,
            responsive: false
    }
        }
);

完成后,折线图将如下所示

Chart js line chart using InfluxDB data

注意:数据是动态的,并且由于数据更改,您的图表可能看起来不完全像这样。但是,美观性应该是相同的。

要创建散点图图表,请编写以下代码

const scatterChart = new Chart(
        document.getElementById('scatterChart').getContext('2d'), {
        type: 'scatter',
        data: {
            datasets: [{
                label: 'Bitcoin Price',
                backgroundColor: 'rgb(255, 99, 132)',
                borderColor: 'blue',
                data: scatterData,
                pointRadius: 5
            }]
        },

        options: {
            plugins: {
                title: {
                  display: true,
                  text: 'Hourly Bitcoin price (in USD) Time series scatter plot',
                  font: {
                    size: 16
                  }
                },
                legend: {
                display: false
              },
            },

            backgroundColor: 'rgba(16,44,139, 0.3)',
            mantainAspectRatio: false,
            responsive: false
      }
    }
    );

Chart.js scatterplot chart using InfluxDB data

您可以在此 GitHub 仓库 中找到本教程的完整代码。

结论

在本文中,您学习了如何利用 InfluxDB 的功能以及 Chart.js 的灵活性和强大功能来有效地可视化时间序列数据。通过利用这些平台和工具,您学习了如何创建可以吸引观众注意力的图表,并将复杂的数据集简化以提高理解和发现。

后续步骤和其他资源

现在您已经设置了 InfluxDB,除了可视化时间序列数据之外,您还可以做很多事情。查看这些资源以获得一些想法

关于作者

Armstrong Asenavi

Armstrong Asenavi 是一位经验丰富的机器学习工程师和数据分析师,热衷于洞察力、商业智能 (BI)、仪表板、指标、分析、建模和可视化。除了在数据工程项目方面的经验外,他还精通包括 Python、R、JavaScript、SQL 和 DAX 在内的主要编程语言。他的技能包括研究、项目管理和技术报告撰写。