【ECharts】使用 ECharts 处理不同时间节点的数据系列展示

使用 ECharts 处理不同时间节点的数据系列展示

在数据可视化中,我们经常遇到这样的问题:不同数据系列的数据点在时间轴上并不对齐。这种情况下,如果直接在 ECharts 中展示,图表可能会出现混乱或不准确。本文将通过一个示例代码,演示如何解决这一问题,使得多个数据系列在同一个图表中能够准确展示。
在这里插入图片描述

问题描述

假设我们有多个测站(stations),每个测站有多个目标(targets),每个目标在不同的时间点采集数据。为了将这些数据在同一个图表中展示,我们需要对时间点进行统一处理,使得每个时间点都有相应的数据值。具体来说,我们需要将数据重新采样到一个统一的时间轴上。

示例代码

以下代码演示了如何将不同时间节点的数据系列重新采样到统一的时间轴上,并生成新的数据结构,以便在 ECharts 中展示。

function aggregateData(stations) {
    // 生成新的时间点,五分钟一个间隔
    function generateTimePoints(startTime, endTime) {
        let times = [];
        let current = new Date(startTime);
        while (current <= endTime) {
            times.push(current.toTimeString().substring(0, 5));
            current.setMinutes(current.getMinutes() + 5);
        }
        return times;
    }

    // 解析时间字符串为Date对象
    function parseTime(timeStr) {
        let parts = timeStr.split(":");
        let date = new Date();
        date.setHours(parseInt(parts[0]), parseInt(parts[1]), 0, 0);
        return date;
    }

    // 初始化新的时间点
    let allProduceTimes = [];
    stations.forEach(station => {
        station.targets.forEach(target => {
            target.produceTime.forEach(time => {
                allProduceTimes.push(parseTime(time));
            });
        });
    });

    let minTime = new Date(Math.min.apply(null, allProduceTimes));
    let maxTime = new Date(Math.max.apply(null, allProduceTimes));
    let newProduceTimes = generateTimePoints(minTime, maxTime);

    // 重新填充数据
    stations.forEach(station => {
        station.targets.forEach(target => {
            let newData = new Array(newProduceTimes.length).fill(0);
            let index = 0;

            target.produceTime.forEach((time, i) => {
                let parsedTime = parseTime(time);

                while (index < newProduceTimes.length && parsedTime >= parseTime(newProduceTimes[index])) {
                    index++;
                }

                if (index > 0) {
                    newData[index - 1] = parseFloat(target.data[i]);
                }
            });

            target.produceTime = newProduceTimes;
            target.data = newData.map(value => value.toFixed(1)); // 保留一位小数
        });
    });

    return stations;
}

// 示例输入
let stations = [
    {
        "inverterno": "2005435242250085",
        "targets": [
            {
                "value": "todayEnergy",
                "unit": 4,
                "data": [
                    "22.3", "23.3", "24.2", "25.2", "26.1", "26.9", "27.8", "28.6", "29.3", "30.0", "30.7", "31.4", "32.0", "32.5", "33.2", "33.8", "34.4", "35.0", "35.6", "36.2"
                ],
                "produceTime": [
                    "05:39", "05:44", "05:49", "05:54", "05:59", "06:04", "06:09", "06:14", "06:19", "06:24", "06:29", "06:34"
                ]
            },
            {
                "value": "totalEnergy",
                "unit": 4,
                "data": [
                    "1797.0", "1797.0", "1798.0", "1799.0", "1799.0", "1800.0", "1801.0", "1801.0", "1802.0", "1802.0", "1803.0", "1804.0"
                ],
                "produceTime": [
                    "05:39", "05:44", "05:49", "05:54", "05:59", "06:04", "06:09", "06:14", "06:19", "06:24", "06:29", "06:34"
                ]
            }
        ]
    },
    {
        "inverterno": "2005435242250086",
        "targets": [
            {
                "value": "todayEnergy",
                "unit": 4,
                "data": [
                    "0.0", "0.0", "0.0", "0.1", "0.1", "0.1", "0.1", "0.1", "0.1", "0.1", "0.2", "0.2", "0.2", "0.3", "0.4", "0.4", "0.5", "0.6", "0.7"
                ],
                "produceTime": [
                    "05:27", "05:32", "05:37", "05:42", "05:47", "05:52", "05:57", "06:02", "06:07", "06:12", "06:17", "06:22"
                ]
            },
            {
                "value": "totalEnergy",
                "unit": 4,
                "data": [
                    "1106.0", "1106.0", "1106.0", "1106.0", "1106.0", "1106.0", "1106.0", "1106.0", "1106.0", "1106.0", "1106.0", "1106.0"
                ],
                "produceTime": [
                    "05:27", "05:32", "05:37", "05:42", "05:47", "05:52", "05:57", "06:02", "06:07", "06:12", "06:17", "06:22"
                ]
            }
        ]
    }
];

let aggregatedStations = aggregateData(stations);
console.log(JSON.stringify(aggregatedStations, null, 2));

代码详解

  1. 生成新的时间点:
    generateTimePoints函数生成一个从startTimeendTime的时间点数组,时间间隔为5分钟。这样我们可以确保所有数据系列的时间点都是对齐的。

  2. 解析时间字符串为Date对象:
    parseTime函数将时间字符串(例如"05:39")解析成Date对象,以便进行时间计算。

  3. 初始化新的时间点:
    遍历所有的测站和目标,收集所有的生产时间点,找到最小时间点和最大时间点,并生成包含所有时间点的数组newProduceTimes

  4. 重新填充数据:
    遍历每个测站和目标,将旧时间点和数据映射到新的时间点数组上。新的数据newData初始化为0数组,然后根据旧时间点填充相应的数值。

在 ECharts 中展示

现在,我们已经将数据重新采样到统一的时间轴上,接下来可以在 ECharts 中展示这些数据。以下是一个简单的 ECharts 配置示例:

var chart = echarts.init(document.getElementById('main'));

var option = {
    tooltip: {
        trigger: 'axis'
    },
    legend: {
        data: ['今日能量', '总能量']
    },
    xAxis: {
        type: 'category',
        data: aggregatedStations[0].targets[0].produceTime
    },
    yAxis: {
        type: 'value'
    },
    series: [
        {
            name: '今日能量',
            type: 'line',
            data: aggregatedStations[0].targets[0].data
        },
        {
            name: '总能量',
            type: 'line',
            data: aggregatedStations[0].targets[1].data
        },
        {
            name: '今日能量2',
            type: 'line',
            data: aggregatedStations[1].targets[0].data
        },
        {
            name: '总能量2',
            type: 'line',
            data: aggregatedStations[1].targets[1].data
        }
    ]
};

chart.setOption(option);

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/803244.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

解决VSCode自动识别文件编码

在VScode 的 设置界面 输入 autoGuess 关键字 &#xff0c;勾选启用即可自动识别&#xff01;&#xff01;&#xff01;

【Python与GUI开发】事件处理与打包分发

文章目录 前言 一、高级事件处理 1.自定义事件 2.拖放操作 3.复杂控件的事件处理 二、打包和分发 Tkinter 应用 1.PyInstaller 2.cx_Freeze 3.spec 文件 4.分发注意事项 三、实战示例&#xff1a;文件浏览器 总结 前言 在前面的讨论中&#xff0c;我们深入理解了 T…

Qt MV架构-委托类

一、基本概念 与MVC模式不同&#xff0c;MV视图架构中没有包含一个完全分离的组件来处理与用户的交互。 一般地&#xff0c;视图用来将模型中的数据显示给用户&#xff0c;也用来处理用户的输入。为了获得更高的灵活性&#xff0c;交互可以由委托来执行。 这些组件提供了输入…

每日一 练,java

目录 题目分析代码 题目 选自牛客网 1.小美的平衡矩阵 小美拿到了一个&#x1d45b;∗&#x1d45b;的矩阵&#xff0c;其中每个元素是 0 或者 1。 小美认为一个矩形区域是完美的&#xff0c;当且仅当该区域内 0 的数量恰好等于 1 的数量。现在&#xff0c;小美希望你回答有多…

电瓶车检测AI算法:视频智能分析技术助力电瓶车规范与安全管理

随着电瓶车&#xff08;电动自行车&#xff09;的普及&#xff0c;其在城市交通中扮演着越来越重要的角色。然而&#xff0c;电瓶车的管理、安全监控以及维护等方面也面临着诸多挑战。近年来&#xff0c;人工智能&#xff08;AI&#xff09;技术的发展为解决这些问题提供了新的…

网络开局 与 Underlay网络自动化

由于出口和核心设备 部署在核心机房,地理位置集中,业务复杂,开局通常需要网络工程师进站调测。 因此核心层及核心以上的设备(包含核心层设备,旁挂独立AC设备和出口设备)推荐采用WEB网管开局方式或命令行开局方式。 核心以下的设备(包含汇聚层设备、接入层设备和AP)由于数量众…

使用 exe4j 转换 Java jar 程序为 Windows 平台可执行文件 (.exe)

使用 exe4j 转换 Java jar 程序为 Windows 平台可执行文件 &#xff08;.exe&#xff09; 介绍exe4j 特点&#xff1a;转换全过程&#xff08;软件操作&#xff09;1、注册2、选择模式3、配置应用4、选择执行的方式&#xff08;我这里管这个叫呈现方式&#xff09;5、选择 JAR …

6.Dockerfile及Dockerfile常用指令

Dockerfile是构建docker镜像的脚本文件 Dockerfile有很多的指令构成&#xff0c;指令由上到下依次运行。 每一条指令就是一层镜像&#xff0c;层越多&#xff0c;体积就越大&#xff0c;启动速度也越慢 井号开头的行是注释行。指令写大写写小写都行&#xff0c;但一般都写为…

Java SpringAOP简介

简介 官方介绍&#xff1a; SpringAOP的全称是&#xff08;Aspect Oriented Programming&#xff09;中文翻译过来是面向切面编程&#xff0c;AOP是OOP的延续&#xff0c;是软件开发中的一个热点&#xff0c;也是Spring框架中的一个重要内容&#xff0c;是函数式编程的一种衍生…

WEB前端05-JavaScrip基本对象

JavaScript对象 1.Function对象 函数的创建 //方法一&#xff1a;自定义函数 function 函数名([参数]) {函数体[return 表达式] }//方法二&#xff1a;匿名函数 (function([参数]) {函数体[return 表达式] }); **使用场景一&#xff1a;定义后直接调用使用(只使用一次) (fun…

《学会 SpringBoot · 定制 SpringMVC》

&#x1f4e2; 大家好&#xff0c;我是 【战神刘玉栋】&#xff0c;有10多年的研发经验&#xff0c;致力于前后端技术栈的知识沉淀和传播。 &#x1f497; &#x1f33b; 近期刚转战 CSDN&#xff0c;会严格把控文章质量&#xff0c;绝不滥竽充数&#xff0c;如需交流&#xff…

【持续集成_06课_Jenkins高级pipeline应用】

一、创建项目选择pipeline的风格 它主要是以脚本&#xff08;它自己的语言&#xff09;的方式进行运行&#xff0c;一般由运维去做的事情&#xff0c;作为测试而言。了解即可。 --- 体现形式全部通过脚本去实现&#xff1a;执行之前&#xff08;拉取代码&#xff09;执行&…

【JavaEE精炼宝库】 初识网络原理——网络通信基础 | 协议

文章目录 一、网络发展史1.1 独立模式&#xff1a;1.2 网络互连&#xff1a;1.3 局域网&#xff08;LAN&#xff09;&#xff1a;1.4 广域网&#xff08;WAN&#xff09;&#xff1a; 二、网络通信基础2.1 IP地址&#xff1a;2.2 端口号&#xff1a; 三、协议3.1 协议的概念&am…

[米联客-安路飞龙DR1-FPSOC] FPGA基础篇连载-18 I2C MASTER控制器驱动设计

软件版本&#xff1a;Anlogic -TD5.9.1-DR1_ES1.1 操作系统&#xff1a;WIN10 64bit 硬件平台&#xff1a;适用安路(Anlogic)FPGA 实验平台&#xff1a;米联客-MLK-L1-CZ06-DR1M90G开发板 板卡获取平台&#xff1a;https://milianke.tmall.com/ 登录“米联客”FPGA社区 ht…

【5G Sub-6GHz模块】专为IoT/eMBB应用而设计的RG520NNA、RG520FEB、RG530FNA、RG500LEU 5G模组

推出全新的5G系列模组&#xff1a; RG520NNADB-M28-SGASA RG520NNADA-M20-SGASA RG520FEBDE-M28-TA0AA RG530FNAEA-M28-SGASA RG530FNAEA-M28-TA0AA RG500LEUAA-M28-TA0AA ——明佳达 1、5G RG520N 系列——专为IoT/eMBB应用而设计的LGA封装模块 RG520N 系列是一款专为 IoT…

Ghost Browser指纹浏览器集成IPXProxy代理IP:解锁Twitch直播新体验

​Twitch 是一个实时视频流平台&#xff0c;允许人们实时播放各自的内容&#xff0c;无论是游戏、娱乐、体育、音乐还是其他内容。不少人的人都想要在Twitch直播来吸引更多的粉丝&#xff0c;然而有时候会面临无法成功使用Twitch的问题。本文将带来Ghost Browser指纹浏览器集成…

网络概念: 互联网和局域网、 OSI七层网络互联模型、数据封装、应用端口、地址解析、网络设备、网络配置

文章目录 引言I 网络概念1.1 互联网和局域网1.2 OSI七层网络互联模型1.3 数据封装1.4 TCP/IP协议1.5 应用端口II 地址解析III 网络设备3.1 集线器 HUB3.2 交换机 swich3.3 路由器 router3.4 防火墙 firewallIV 网络配置4.1 网络安全域(你住哪里?)4.2 地址转换(NAT,你名字叫…

Go 1.19.4 函数-Day 08

1. 函数概念和调用原理 1.1 基本介绍 函数是基本的代码块&#xff0c;用于执行一个任务。 Go 语言最少有个 main() 函数。 你可以通过函数来划分不同功能&#xff0c;逻辑上每个函数执行的是指定的任务。 函数声明告诉了编译器函数的名称&#xff0c;返回类型&#xff0c;和参…

Windows与Ubuntu安装ffmpeg

文章目录 前言ffmpeg的简介安装ffmpegWindows下载设置环境变量 Ubuntu 总结 前言 FFmpeg是一款非常强大的开源音视频处理工具&#xff0c;它包含了众多的音视频编解码库&#xff0c;可以用于音视频的采集、编解码、转码、流化、过滤和播放等复杂的处理。在Windows系统上安装FF…

一五六、Node+Vue 使用七牛上传图片,并配置个人域名

1. 七牛云ak/sk获取 点击注册&#x1f517;开通七牛开发者帐号如果已有账号&#xff0c;直接登录七牛开发者后台&#xff0c;点击这里&#x1f517;查看 Access Key 和 Secret Key 2. Node.js获取七牛token 安装qiniu npm install qiniu创建空间 Node获取token const qi…