gpt4 book ai didi

javascript - 当 x 值不完全匹配时,如何使用 d3.js 将多个折线图正确聚合/分组为一个总体图?

转载 作者:行者123 更新时间:2023-12-02 23:27:54 25 4
gpt4 key购买 nike

我有多个这样的数据集:

const server1 = [
{ date: '2019-06-15T00:22:25.000Z', online: 451 },
{ date: '2019-06-15T01:08:58.000Z', online: 499 }
];

const server2 = [
{ date: '2019-06-15T00:14:18.000Z', online: 599 },
{ date: '2019-06-15T00:58:56.000Z', online: 554 }
];

const server3 = [
{ date: '2019-06-15T00:10:18.000Z', online: 321 },
{ date: '2019-06-15T00:54:56.000Z', online: 300 }
];

我设法为它们每个人绘制了一个折线图,图表如下所示:enter image description here

但现在我想绘制一个额外的折线图,将每个图的数据聚合成一个单独的图,以便它显示所有服务器的总体在线数量的估计。

我不知道如何处理这个问题,因为日期(x 值)不完全匹配,所以我不能简单地将这些值相加。

Here is a jsfiddle with the code I have so far

<小时/>

更新1:

这是我根据 Coderino Javarino 的建议组合而成的函数:

const mergeDatasets = (xPropName, yPropName, ...datasets) => {
const makeScale = dataset => {
return d3
.scaleTime()
.domain(dataset.map(obj => new Date(obj[xPropName])))
.range(dataset.map(obj => obj[yPropName]));
};
const sumOtherDataSets = (scales, object, curDataSetIndex) => {
let sum = object[yPropName];
scales.forEach((_scale, scaleIndex) => {
if (curDataSetIndex !== scaleIndex) {
sum += scales[scaleIndex](new Date(object[xPropName]));
}
});
return sum;
};

// make a scale for each dataset
const scales = datasets.map(dataset => makeScale(dataset));

/* make an new array where each datapoint is summed with the interpolated
/* counterparts from all other datasets */
let merged = [];
datasets.forEach((dataset, curDataSetIndex) => {
const summedDataset = dataset.map(object => {
const objCopy = { ...object };
objCopy[yPropName] = sumOtherDataSets(scales, object, curDataSetIndex);
return objCopy;
});
merged = [].concat(merged, summedDataset);
});

// restore the correct order by date
merged = merged.sort((a, b) => new Date(a[xPropName]) - new Date(b[xPropName]));
return merged;
};

然后我可以像这样轻松地使用它:

    const merged = mergeDatasets("date", "online", server1, server2, server3);

但它有一个缺陷,即当它必须插入超出特定比例域范围的点时,整体图形是不正确的。

enter image description here

Here is an updated fiddle that also shows the problem

最佳答案

我采取的方法是:

  1. 提取所有 x 值,其中至少一行具有指定的值。
  2. 为每条线创建比例,其中域是其所有 x 点,范围是其所有 y 点
  3. 循环遍历 x 列表,获取每行的插值 y 值,然后相加。

诚然,我对 d3-interpolation 包不太熟悉,所以可能有更好的方法来执行它。尽管如此,这仍然有效。

const server1 = [
{ date: '2019-06-15T00:22:25.000Z', online: 451 },
{ date: '2019-06-15T01:08:58.000Z', online: 499 },
{ date: '2019-06-15T02:25:35.000Z', online: 464 },
{ date: '2019-06-15T13:25:42.000Z', online: 252 },
{ date: '2019-06-15T15:45:24.000Z', online: 247 },
{ date: '2019-06-15T17:02:09.000Z', online: 254 },
{ date: '2019-06-15T20:11:00.000Z', online: 300 },
{ date: '2019-06-15T21:22:33.000Z', online: 296 },
{ date: '2019-06-15T22:24:58.000Z', online: 298 },
{ date: '2019-06-15T22:58:18.000Z', online: 270 }
];

const server2 = [
{ date: '2019-06-15T00:14:18.000Z', online: 599 },
{ date: '2019-06-15T00:58:56.000Z', online: 554 },
{ date: '2019-06-15T02:15:13.000Z', online: 505 },
{ date: '2019-06-15T13:32:19.000Z', online: 221 },
{ date: '2019-06-15T15:19:08.000Z', online: 265 },
{ date: '2019-06-15T16:04:55.000Z', online: 277 },
{ date: '2019-06-15T17:31:16.000Z', online: 275 },
{ date: '2019-06-15T18:41:16.000Z', online: 303 },
{ date: '2019-06-15T20:05:41.000Z', online: 333 },
{ date: '2019-06-15T21:39:44.000Z', online: 288 },
{ date: '2019-06-15T22:46:01.000Z', online: 277 },
{ date: '2019-06-15T23:29:16.000Z', online: 264 }
];

const server3 = [
{ date: '2019-06-15T00:10:18.000Z', online: 321 },
{ date: '2019-06-15T00:54:56.000Z', online: 300 },
{ date: '2019-06-15T02:11:13.000Z', online: 280 },
{ date: '2019-06-15T13:28:19.000Z', online: 110 },
{ date: '2019-06-15T15:15:08.000Z', online: 130 },
{ date: '2019-06-15T16:01:55.000Z', online: 133 },
{ date: '2019-06-15T17:25:16.000Z', online: 140 },
{ date: '2019-06-15T18:37:16.000Z', online: 172 },
{ date: '2019-06-15T20:01:41.000Z', online: 180 },
{ date: '2019-06-15T21:35:44.000Z', online: 201 },
{ date: '2019-06-15T22:41:01.000Z', online: 210 },
{ date: '2019-06-15T23:23:16.000Z', online: 197 }
];

var x_list = [].concat(server1, server2, server3)
.map(d => new Date(d.date))
.sort(d3.ascending);

var servers_scales = [server1, server2, server3].map(s => {
return d3.scaleLinear()
.domain(s.map(d => new Date(d.date)))
.range(s.map(d => d.online));
});

var combinedData = x_list.map(x => {
var val = 0;
for (var i = 0; i < servers_scales.length; i++)
val += servers_scales[i](x);
return {
date: x,
online: val
};
});


const combined = [].concat(server1, server2, server3);

const margin = {top: 50, right: 50, bottom: 50, left: 50};
const width = window.innerWidth - margin.left - margin.right;
const height = window.innerHeight - margin.top - margin.bottom;

const dateMin = d3.min(combined, d => new Date(d.date));
const dateMax = d3.max(combined, d => new Date(d.date));
const onlineMin = d3.min(combined, d => d.online);
const onlineMax = d3.max(combined, d => d.online);

const xScale = d3
.scaleTime()
.domain([dateMin, dateMax])
.range([0, width]);

const yScale = d3
.scaleLinear()
.domain([0, onlineMax * 3])
.range([height, 0]);

const line = d3
.line()
.x(d => xScale(new Date(d.date)))
.y(d => yScale(d.online))
.curve(d3.curveMonotoneX);

const svg = d3
.select('body')
.append('svg')
.attr('width', width + margin.left + margin.right)
.attr('height', height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");

svg
.append('path')
.datum(server1)
.attr('class', 'line')
.attr('fill', 'none')
.attr('stroke', 'blue')
.attr('d', line);

svg
.append('path')
.datum(server2)
.attr('class', 'line')
.attr('fill', 'none')
.attr('stroke', 'red')
.attr('d', line);

svg
.append('path')
.datum(server3)
.attr('class', 'line')
.attr('fill', 'none')
.attr('stroke', 'green')
.attr('d', line);

svg
.append('path')
.datum(combinedData)
.attr('class', 'line')
.attr('fill', 'none')
.attr('stroke', 'orange')
.attr('d', line);

svg
.append("g")
.attr("class", "y axis")
.call(d3.axisLeft(yScale));

svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(xScale));
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>

关于javascript - 当 x 值不完全匹配时,如何使用 d3.js 将多个折线图正确聚合/分组为一个总体图?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56652797/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com