javascript - D3js : How to interpolate datasets with irregular time intervals before stacking them?

标签 javascript d3.js data-visualization

更新: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 添加了几行以处理数据。

首先,我需要 super 时间集:

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 

您可以查看更新的 fiddle here

关于javascript - D3js : How to interpolate datasets with irregular time intervals before stacking them?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20806789/

相关文章:

javascript - 哪个是定义函数的更好方法?

d3.js - 如何更改力布局中节点之间的距离?

javascript - 爸爸解析为文件类型输入提供类型错误对象可能为空

javascript - function.apply.bind 在以下代码中如何工作?

javascript - slider jquery + 在页面加载时调用javascript函数的约束来调用javascript函数

javascript - 添加另一个 js 文件中存在的方法的事件监听器

Python - Altair - 带选择的堆积条形图

javascript - 在 D3 JS 中将 div 放置在图表的左上角

maps - 如何可视化 map 内置数据 block 中的数据(点)?

javascript - jquery/javascript 将纯文本消息转换为文本输入字段