dc.js 折线图 - 填充缺失日期并在没有数据时显示零
dc.js lineChart - fill missing dates and show zero where no data
我有一个显示每小时事件数的 dc.js 折线图。我不想加入两个已知值之间的线,而是应该将值显示为零。
所以对于下面的数据,我希望在上午 10 点将线路降为零
{datetime: "2018-05-01 09:10:00", event: 1}
{datetime: "2018-05-01 11:30:00", event: 1}
{datetime: "2018-05-01 11:45:00", event: 1}
{datetime: "2018-05-01 12:15:00", event: 1}
var eventsByDay = facts.dimension(function(d) { return d3.time.hour(d.datetime);});
var eventsByDayGroup = eventsByDay.group().reduceCount(function(d) { return d.datetime; });
我看过 defined 但我认为这不对,我想我需要在没有数据的每个小时的数据中添加零值?但是我不确定如何去做,而且我似乎无法在 dc.js
中找到我正在尝试的示例
另一个问题确实回答了这个问题,但 d3.js 我不确定如何翻译它 - d3 linechart - Show 0 on the y-axis without passing in all points?
谁能指出我正确的方向?
谢谢!
ensure_group_bins
你走在正确的轨道上,但在这种情况下,我们需要计算它们,而不是事先知道所需的 bin 集。
幸运的是 d3 提供了 interval.range 其中 returns 两个日期之间的每个间隔边界的日期数组。
然后我们需要对集合与原始组中的 bin 进行合并排序。也许我稍微过度设计了这个,但这里有一个函数可以做到这一点:
function fill_intervals(group, interval) {
return {
all: function() {
var orig = group.all().map(kv => ({key: new Date(kv.key), value: kv.value}));
var target = interval.range(orig[0].key, orig[orig.length-1].key);
var result = [];
for(var oi = 0, ti = 0; oi < orig.length && ti < target.length;) {
if(orig[oi].key <= target[ti]) {
result.push(orig[oi]);
if(orig[oi++].key.valueOf() === target[ti].valueOf())
++ti;
} else {
result.push({key: target[ti], value: 0});
++ti;
}
}
if(oi<orig.length)
Array.prototype.push.apply(result, orig.slice(oi));
if(ti<target.length)
Array.prototype.push.apply(result, target.slice(ti).map(t => ({key: t, value: 0})));
return result;
}
}
}
基本上我们迭代原始 bins 和目标 bins,取较低的那个。如果它们相同,那么我们增加两个计数器;否则我们只增加较低的那个。
最后,当任一数组有 运行 输出时,我们附加来自另一个数组的所有剩余结果。
Here is an example fiddle based on your code.
它是用 D3v4 编写的,但您只需将两个地方的 d3.timeHour
更改为 d3.time.hour
即可与 D3v3 一起使用。
我会将此功能添加到常见问题解答中!
我有一个显示每小时事件数的 dc.js 折线图。我不想加入两个已知值之间的线,而是应该将值显示为零。
所以对于下面的数据,我希望在上午 10 点将线路降为零
{datetime: "2018-05-01 09:10:00", event: 1}
{datetime: "2018-05-01 11:30:00", event: 1}
{datetime: "2018-05-01 11:45:00", event: 1}
{datetime: "2018-05-01 12:15:00", event: 1}
var eventsByDay = facts.dimension(function(d) { return d3.time.hour(d.datetime);});
var eventsByDayGroup = eventsByDay.group().reduceCount(function(d) { return d.datetime; });
我看过 defined 但我认为这不对,我想我需要在没有数据的每个小时的数据中添加零值?但是我不确定如何去做,而且我似乎无法在 dc.js
中找到我正在尝试的示例另一个问题确实回答了这个问题,但 d3.js 我不确定如何翻译它 - d3 linechart - Show 0 on the y-axis without passing in all points?
谁能指出我正确的方向?
谢谢!
ensure_group_bins
你走在正确的轨道上,但在这种情况下,我们需要计算它们,而不是事先知道所需的 bin 集。
幸运的是 d3 提供了 interval.range 其中 returns 两个日期之间的每个间隔边界的日期数组。
然后我们需要对集合与原始组中的 bin 进行合并排序。也许我稍微过度设计了这个,但这里有一个函数可以做到这一点:
function fill_intervals(group, interval) {
return {
all: function() {
var orig = group.all().map(kv => ({key: new Date(kv.key), value: kv.value}));
var target = interval.range(orig[0].key, orig[orig.length-1].key);
var result = [];
for(var oi = 0, ti = 0; oi < orig.length && ti < target.length;) {
if(orig[oi].key <= target[ti]) {
result.push(orig[oi]);
if(orig[oi++].key.valueOf() === target[ti].valueOf())
++ti;
} else {
result.push({key: target[ti], value: 0});
++ti;
}
}
if(oi<orig.length)
Array.prototype.push.apply(result, orig.slice(oi));
if(ti<target.length)
Array.prototype.push.apply(result, target.slice(ti).map(t => ({key: t, value: 0})));
return result;
}
}
}
基本上我们迭代原始 bins 和目标 bins,取较低的那个。如果它们相同,那么我们增加两个计数器;否则我们只增加较低的那个。
最后,当任一数组有 运行 输出时,我们附加来自另一个数组的所有剩余结果。
Here is an example fiddle based on your code.
它是用 D3v4 编写的,但您只需将两个地方的 d3.timeHour
更改为 d3.time.hour
即可与 D3v3 一起使用。
我会将此功能添加到常见问题解答中!