优化一组dc.js折线图

Iro*_*Man 8 javascript optimization d3.js crossfilter dc.js

我有一组图表为我(这里)可视化一堆数据,基于csv,大约有25,000行数据,每行有12个参数.但是,这样做的任何交互(如选择与任何图形的刷范围)是缓慢和笨拙,完全不像在dc.js试玩这里找到,其中有数以千计的记录,以及交易,但保持流畅的动画,或crossfilter的在这里演示的记录(航班)数量是我的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])); 
Run Code Online (Sandbox Code Playgroud)

单独但相关的问题; 如何修改折线图上的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;
    }
});
Run Code Online (Sandbox Code Playgroud)

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

编辑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;
            } );
        }
    };
Run Code Online (Sandbox Code Playgroud)

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

Gor*_*don 4

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

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

我建议将其减少到 100-1000 个垃圾箱之间,例如每天进行平均:

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);
Run Code Online (Sandbox Code Playgroud)

来自常见问题解答的可重用平均归约函数)

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

chart.xUnits(d3.time.days)
   .elasticY(true)
Run Code Online (Sandbox Code Playgroud)