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

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

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

问题描述

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

示例代码

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

javascript 复制代码
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 配置示例:

javascript 复制代码
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);
相关推荐
小蜜蜂嗡嗡2 小时前
【flutter对屏幕底部有手势区域(如:一条横杠)导致出现重叠遮挡】
前端·javascript·flutter
伍哥的传说3 小时前
Vue 3 useModel vs defineModel:选择正确的双向绑定方案
前端·javascript·vue.js·definemodel对比·usemodel教程·vue3.4新特性·vue双向绑定
WSSWWWSSW6 小时前
Seaborn数据可视化实战:Seaborn数据可视化基础-从内置数据集到外部数据集的应用
python·信息可视化·数据分析·matplotlib·seaborn
Small___ming6 小时前
Matplotlib 可视化大师系列(七):专属篇 - 绘制误差线、等高线与更多特殊图表
python·信息可视化·matplotlib
TDengine (老段)7 小时前
TDengine IDMP 应用场景:工业锅炉监控
大数据·数据库·物联网·信息可视化·时序数据库·tdengine
胡gh8 小时前
页面卡成PPT?重排重绘惹的祸!依旧性能优化
前端·javascript·面试
言兴8 小时前
# 深度解析 ECharts:从零到一构建企业级数据可视化看板
前端·javascript·面试
山有木兮木有枝_8 小时前
TailWind CSS
前端·css·postcss
烛阴9 小时前
TypeScript 的“读心术”:让类型在代码中“流动”起来
前端·javascript·typescript
杨荧9 小时前
基于Python的农作物病虫害防治网站 Python+Django+Vue.js
大数据·前端·vue.js·爬虫·python