javascript - 优化一组dc.js折线图

标签 javascript optimization d3.js dc.js crossfilter

我有一组图表为我可视化一堆数据 (here),基于一个包含大约 25,000 行数据的 csv,每行有 12 个参数。然而,进行任何交互(例如在任何图表上使用画笔选择一个范围)都是缓慢且笨拙的,完全不像the dc.js demo found here。 ,它也处理数千条记录但保持流畅的动画,或 crossfilter's demo here它的记录(航类)数量是我的 10 倍。

我知道主要的资源消耗是两个折线图,因为它们每 15 分钟就有一个数据点,持续大约 8 个整月。删除它们中的任何一个都会使图表再次响应,但它们是可视化的主要特征,所以有什么方法可以让它们显示较少的细粒度数据?

两个折线图的具体代码如下:

        var lineZoomGraph = dc.lineChart("#chart-line-zoom")
            .width(1100)
            .height(60)
            .margins({top: 0, right: 50, bottom: 20, left: 40})
            .dimension(dateDim)
            .group(tempGroup)
            .x(d3.time.scale().domain([minDate,maxDate]));

        var tempLineGraph = dc.lineChart("#chart-line-tempPer15Min")
            .width(1100).height(240)
            .dimension(dateDim)
            .group(tempGroup)
            .mouseZoomable(true)
            .rangeChart(lineZoomGraph)
            .brushOn(false)
            .x(d3.time.scale().domain([minDate,maxDate])); 

独立但相关的问题;如何修改折线图上的 y 轴?默认情况下,它们不包含数据集中的最高值和最低值,这看起来很奇怪。

编辑:我写的一些代码来尝试解决问题:

var graphWidth = 1100;
var dataPerPixel = data.length / graphWidth;

var tempGroup = dateDim.group().reduceSum(function(d) {
    if (d.pointNumber % Math.ceil(dataPerPixel) === 0) {
        return d.warmth;
    }
});

d.pointNumber 是每个数据点的唯一点 ID,从 0 到 22000 ish 累计。但是现在折线图显示为空白。我使用 tempGroup.all() 检查了组的数据,现在每 21 个数据点都有一个温度值,但所有其他数据点都有 NaN。我根本没有成功地减少组的大小;它仍然在22000左右。我想知道这是否是正确的方法...

编辑 2:找到了不同的方法。我通常创建 tempGroup,但随后创建另一个组来进一步过滤现有的 tempGroup。

var tempGroup = dateDim.group().reduceSum(function(d) { return d.warmth; });
    var filteredTempGroup = {
        all: function () {
            return tempGroup.top(Infinity).filter( function (d) { 
                if (d.pointNumber % Math.ceil(dataPerPixel) === 0) return d.value;
            } );
        }
    };

我在这里遇到的问题是 d.pointNumber 不可访问,所以我无法判断它是否是第 N 个数据点(或它的倍数)。如果我将它分配给一个 var,它无论如何都只是一个固定值,所以我不确定如何解决这个问题......

最佳答案

在处理基于 d3 的图表的性能问题时,通常的罪魁祸首是 DOM 元素的数量,而不是数据的大小。请注意,crossfilter 演示有很多行数据,但只有几百条。

看起来您可能试图绘制所有点而不是聚合它们。我想因为你正在做一个时间序列,所以聚合点可能不直观,但考虑到你的绘图只能显示 1100 个点(宽度),所以过度使用 SVG 引擎绘制 25,000 个点是没有意义的。

我建议将其降低到 100-1000 个 bin 之间的某个位置,例如通过平均每一天:

var daysDim = data.dimension(function(d) { return d3.time.day(d.time); });

function reduceAddAvg(attr) {
  return function(p,v) {
    if (_.isLegitNumber(v[attr])) {
      ++p.count
      p.sums += v[attr];
      p.averages = (p.count === 0) ? 0 : p.sums/p.count; // gaurd against dividing by zero
    }
    return p;
  };
}
function reduceRemoveAvg(attr) {
  return function(p,v) {
    if (_.isLegitNumber(v[attr])) {
      --p.count
      p.sums -= v[attr];
      p.averages = (p.count === 0) ? 0 : p.sums/p.count;
    }
    return p;
  };
}
function reduceInitAvg() {
  return {count:0, sums:0, averages:0};
}
...
// average a parameter (column) named "param" 
var daysGroup = dim.group().reduce(reduceAddAvg('param'), reduceRemoveAvg('param'), reduceInitAvg);

(可重复使用的平均归约函数 from the FAQ )

然后指定要匹配的 xUnits,并使用 elasticY 自动计算 y 轴:

chart.xUnits(d3.time.days)
   .elasticY(true)

关于javascript - 优化一组dc.js折线图,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29594395/

相关文章:

delphi - 如何缓存函数 bool 结果

javascript - 如何使用 d3.drag 处理散点图中的比例

javascript - 使用来自 bl.ocks.org 的力导向图示例

Javascript - 在对象数组中查找(而不是删除)具有重复属性的元素

javascript - 如何使用 ajax javascript php 将大型 json 数据(250kb)发送到 mysql 数据库

javascript - 使用 Dropzone.js 在服务器上存储图像缩略图

Python 如何提高 numpy 数组性能?

javascript - jquery animate scrollTop 位置/偏移量不起作用

php - 如何更快地创建索引?

javascript - 在 D3 Javascript 可视化中使用 JSON 数据