我有一组图形,这些图形以csv为基础,为我可视化一堆数据(here),其中包含大约25,000行数据,每行有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到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;
            } );
        }
    };

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

最佳答案

当处理基于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);

(可重用的平均减少函数from the FAQ)

然后指定要匹配的xUnits,并使用elasticY自动计算y轴:
chart.xUnits(d3.time.days)
   .elasticY(true)

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

10-12 15:20