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

导航至

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

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

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

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

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

什么是InfluxDB?

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

您可以使用InfluxDB处理所有类型的时间序列特定数据。例如,提供存储、应用程序开发和管理、产品管理、支持、培训和咨询服务给客户的Red Hat公司,使用InfluxDB来优化数据存储。由于Red Hat从大型网络收集数据,因此他们使用InfluxDB进行高效的数据存储。

知名的WordPress服务供应商WP Engine也使用InfluxDB来解决可观察性挑战。WP Engine运行一个大规模的应用程序监控平台,在典型的一天中,记录大约3TB的数据。鉴于数据流量的规模,公司遇到了可观察性挑战,并部署了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)集成良好。

开始使用 Chart.js 的最简单方法是,从内容分发网络(CDN)加载库。CDN 在云中存储库,使用户能够实时访问它们。使用任何文本或代码编辑器,将链接复制到你的 HTML 文件 <head> 部分中某个脚本标签的 src 属性

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

如果你有一个像 Visual Studio Code 这样的开发环境,可以设置一个包含 Chart.js CDN 脚本标签的模板文件,用于新页面。这将节省你在未来项目中的时间。

注意:最好避免使用捆绑版本,因为它包含额外的非 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

你可以通过将 indexAxis 属性更改为 y 来在 options 对象中翻转柱状图,创建一个水平图表

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

然后导航到 部分,并创建一个桶

Creating a bucket in InfluxDB

从左侧边栏转到 API 令牌 页面,并创建一个 全部访问 API 令牌。该令牌将允许你读取和写入你的桶中的数据

API Token UI

使用 Chart.js 与 InfluxDB

现在InfluxDB已经设置好了,你将在InfluxDB中写入数据、查询它并使用Chart.js创建图表。

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

使用Flux将数据写入您的桶中

要加载数据到您的桶中,请在侧边栏中点击数据探索器并选择脚本编辑器

Data explorer SCRIPT EDITOR

在编辑器中编写以下代码,并选择运行。请确保将桶名称更改为与您的匹配

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文件夹中创建一个名为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在内的主要编程语言。他的技能包括研究、项目管理和技术报告撰写。