更新:jsfiddle示例说明了此问题:http://jsfiddle.net/T8SuH/
我对D3js和JavaScript还是陌生的,但是对Java很满意。我有一个来自自行车共享系统的大型CSV数据集,其组织如下:
event_id, station_id, timestamp, number_of_bikes, number_of_empty_docks
为了减小文件大小,我的数据文件仅包含各个工作站的新事件。因此,不同站点的时间戳既不是规则的时间间隔,也不是重合的。例如,连续的条目可能如下所示:
31044955, 08, 2012-05-01 00:00:00, 9, 6
31044965, 23, 2012-05-01 00:32:00, 2, 6
31044972, 02, 2012-05-01 00:44:00, 10, 5
31044999, 17, 2012-05-01 02:10:10, 12, 6
...
我想创建一个堆积的面积图,其中x轴是时间(24小时),y轴是(堆积)来自选定站点的库存。 D3 Wiki提到在计算堆栈之前应先对数据进行插值。我考虑了两种方法:
-在D3之外(使用Java)对我的数据集进行插值,并将其另存为新的CSV文件,其中所有工作站都具有并发时间戳。这种方法会使文件大小增加6倍以上(当前为25MB),而且我担心D3的处理速度会变慢。
-在进行堆栈或绘制区域/路径之前,先在D3 / Javascript中插入数据。
虽然我认为第二种方法会更快(就性能而言),但我不知道该怎么做,也没有找到任何相关的教程/示例。我只是猜测我将不得不创建一个范围(d3.time.minute.range),然后将其与map()函数一起使用以创建新的数组?有人可以提出建议,说明如何在D3内将多个数据集(例如,每个电台)以不规则的时间间隔进行插值之前将其插值吗?
先感谢您。
最佳答案
我曾经遇到过同样的问题。稍加精致,您就可以添加缺少的值,以便每个系列都具有相同的x坐标集(时间戳)。我将几行代码添加到jsfiddle中,以在将数据发送到堆栈布局之前对数据进行按摩。
首先,我需要时间超集:
var times = [];
myData.forEach(function(d) {
if(times.indexOf(d.date.getTime()) === -1) {
times.push(d.date.getTime());
}
});
times.sort();
这将导致数组(根据您的数据):
0:00, 4:00, 4:30, 4:45, 8:08, 12:08, 13:08, 16:08, 20:08
请注意,最后我对它进行了排序,因为这实际上将简化在站数据序列中查找缺失值的过程。我打算进行某种排序的列表合并,以将不变的数据值填充到系列中。直接从数据(时间值对)中得出的系列如下所示:
Initial series
Station_1 0:00 37, 4:30 36, 8:08 18, 12:08 10, 16:08 32, 20:08 35
Station_2 0:00 32, 4:00 29, 8:08 6, 12:08 12, 16:08 29, 20:08 32
Station_3 0:00 36, 4:45 30, 8:08 10, 13:08 13, 16:08 32, 20:08 36
Station_4 0:00 31, 4:00 28, 8:08 12, 12:08 14, 16:08 28, 20:08 31
因此,对于每个系列,遍历时间数组并插入缺失值,可能有一种更有效的方法:
myNestedData.forEach(function(stationData) {
stationData.values.sort(function(a,b) {
return d3.ascending(a.date.getTime(), b.date.getTime());
});
var j = 0;
var lastStationValue = 0;
for(var i = 0; i < times.length; i++) {
// If the station series is too short I should not equal any
// value from the times array
stationTime = j <= stationData.values.length ?
stationData.values[j].date.getTime() : 0;
if(times[i] !== stationTime) {
// Missing values need to be spliced in.
stationData.values.splice(j, 0, {
date: new Date(times[i]),
inventory: lastStationValue,
station_id: stationData.key
});
j++;
}
else {
// We have a value for this time, move along.
lastStationValue = stationData.values[j].inventory;
j++;
}
}
});
现在该系列应该全部排队!
Station_1 0:00 37, 4:00 37, 4:30 36, 4:45 36, 8:08 18, 12:08 10, 13:08 10, 16:08 32, 20:08 35
Station_2 0:00 32, 4:00 29, 4:30 29, 4:45 29, 8:08 6, 12:08 12, 13:08 12, 16:08 29, 20:08 32
Station_3 0:00 36, 4:00 36, 4:30 36, 4:45 30, 8:08 10, 12:08 10, 13:08 13, 16:08 32, 20:08 36
Station_4 0:00 31, 4:00 28, 4:30 28, 4:45 28, 8:08 12, 12:08 14, 13:08 14, 16:08 28, 20:08 31
您可以查看更新的小提琴here