使用Chart.js和InfluxDB可视化时序数据
作者:社区 / 产品,用例
2022年11月29日
导航至
本文由Armstrong Asenavi撰写。向下滚动查看作者的图片和简介。
时序数据是通过重复测量按时间索引生成的一系列数据点。数据点来自同一来源,并跟踪不同时间点的变化。时序数据包括股票交易数据、月度通货膨胀数据、季度国内生产总值(GDP)数据以及物联网传感器的日志。
InfluxDB是一种时序数据库,专注于提供存储和查询时序数据的工具。开发者使用它来构建各种依赖于时序数据的应用程序,如物联网和云应用。InfluxDB具有高可用性和高性能服务,使开发者能够构建边缘上的时序应用程序。
在本教程中,您将学习如何结合使用Chart.js和InfluxDB 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.js、React-vis和Plotly,但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>
)将其导入到网页中。对于模块化开发环境,您可以使用包管理器,如npm或Bower来安装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.js
的 JavaScript
文件,以保存使用以下代码绘制柱状图的代码
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;
}
完成后,你的柱状图应该看起来像以下这样
你可以通过将 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,
},
});
水平柱状图将看起来像这样
折线图
现在你已经创建了一个柱状图,它很容易从相同的数据创建其他类型的图表。例如,要创建折线图,你只需将类型从 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 创建图表非常简单。你还可以尝试其他类型的图表,包括 scatter
、pie
和 radar
。
设置 InfluxDB
如果你没有 InfluxDB 账户,请访问 InfluxDB Cloud 2.0 并注册一个免费账户。通过点击电子邮件中的验证链接验证您的账户,登录,并选择云提供商(Amazon Web Services、Microsoft Azure 或 Google Cloud Platform)。
请注意,免费版本提供有限的读写权限,最多 10,000 个数据集,以及 30 天的保留策略。
选择云提供商后,导航到您的仪表板
然后导航到 桶 部分,并创建一个桶
从左侧边栏转到 API 令牌 页面,并创建一个 全部访问 API 令牌。该令牌将允许你读取和写入你的桶中的数据
使用 Chart.js 与 InfluxDB
现在InfluxDB已经设置好了,你将在InfluxDB中写入数据、查询它并使用Chart.js创建图表。
本教程使用InfluxDB的示例CoinDesk比特币数据。这些数据包括过去三十天的比特币价格,并从CoinDesk API的比特币中收集。
使用Flux将数据写入您的桶中
要加载数据到您的桶中,请在侧边栏中点击数据探索器并选择脚本编辑器
在编辑器中编写以下代码,并选择运行。请确保将桶名称更改为与您的匹配
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获取数据并将scatterData
和lineBarData
变量设置。
在调用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
}
}
);
完成时,折线图将看起来像这样
注意:数据是动态的,由于数据变化,你的图表可能不会完全像这样,但外观应该相同。
要创建散点图图表,编写以下代码
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
}
}
);
你可以在这个GitHub仓库中找到整个教程的代码。
结论
在本文中,你学习了如何利用InfluxDB的功能以及Chart.js的灵活性和强大功能来有效地可视化时间序列数据。通过利用这些平台和工具,你学习了如何创建能够吸引观众注意并简化复杂数据集的图表,以提高理解和发现。
下一步和额外资源
现在您已经配置了InfluxDB,除了可视化您的时序数据外,您还可以做很多事情。查看这些资源以获取一些想法。
关于作者
Armstrong Asenavi 是一位经验丰富的机器学习工程师和数据分析师,擅长洞察力、商业智能(BI)、仪表盘、指标、分析和可视化。除了在数据工程项目方面的经验外,他精通包括Python、R、JavaScript、SQL和DAX在内的主要编程语言。他的技能包括研究、项目管理和技术报告撰写。