如何调整 dc.js 和交叉过滤器的装箱?那是性能瓶颈吗?

How do I tweak binning for dc.js and crossfilter? Is that the performance bottleneck?

我正在尝试制作一个可以接受 csv 并构建仪表板的通用交叉过滤器。以下是工作示例:

但由于某些原因,航班数据缓慢且无响应。比较分析相同数据的这两个:

我认为这是因为直方图合并太详细了,但我在 api 参考中找不到调整它的好方法。 @gordonwoodhull mentioned:

If the binning is wrong you really want to look at the way you've set up crossfilter - dc.js just uses what it is given.

如何调整交叉过滤器的合并?我试过弄乱 xUnitsdimensiongroup 舍入但无济于事。

This is the problem code I suspect is slow/wrong:

    var dim = ndx.dimension(function (d) { return d[propName]; });

    if (isNumeric(data[0][propName])) {
        var theChart = dc.barChart("#" + chartId);

        var countGroup = dim.group().reduceCount();
        var minMax = d3.extent(data, function (d) { return +d[propName] });
        var min = +minMax[0];
        var max = +minMax[1];
        theChart
            .width(gfilter.width).height(gfilter.height)
            .dimension(dim)
            .group(countGroup)
            .x(d3.scale.linear().domain([min, max]))
            .elasticY(true);
        theChart.yAxis().ticks(2);

您可以通过将调整值的函数传递给 group() 方法来调整分箱。例如,这个组将创建整数 bin:

var countGroup = dim.group(function (v) { return Math.floor(v); });

而这个会创建 20 个单位的箱子:

var countGroup = dim.group(function(d) { return Math.floor(d / 20) * 20 });

分解出 bin 大小的变量:

var bin = 20;  // or any integer
var countGroup = dim.group(function(d) { return Math.floor(d / bin) * bin });

如果您使用分箱,您可能还希望条形的宽度与分箱大小相匹配。为此,请在条形图上添加对 xUnits() 的调用。 xUnits()设置轴上的点数:

.xUnits(function(start, end, xDomain) { return (end - start) / bin; }) 

请参阅 crossfilter dimension group(), dc.js xUnits()

的文档

您可以在以下位置查看结果:

https://ubershmekel.github.io/gfilter/?dl=testData/Sacramentorealestatetransactions.csv

这对我有用。我必须避免 3 个陷阱:group() 函数需要四舍五入到柱的位置,xUnits 需要柱的数量,并使 domain(x 轴)显示最大值。

var numericValue = function (d) {
    if (d[propName] === "")
        return NaN;
    else
        return +d[propName];
};
var dimNumeric = ndx.dimension(numericValue);
var minMax = d3.extent(data, numericValue);
var min = minMax[0];
var max = minMax[1];
var barChart = dc.barChart("#" + chartId);
// avoid very thin lines and a barcode-like histogram
var barCount = 30;
var span = max - min;
lastBarSize = span / barCount;
var roundToHistogramBar = function (d) {
    if (isNaN(d) || d === "")
        d = NaN;
    if (d == max)
        // This fix avoids the max value always being in its own bin (max).
        // I should figure out how to make the grouping equation better and avoid this hack. 
        d = max - lastBarSize;
    var res = min + span * Math.floor(barCount * (d - min) / span) / barCount;
    return res;
};
var countGroup = dimNumeric.group(roundToHistogramBar);
barChart.xUnits(function () { return barCount; });
barChart
    .width(gfilter.width).height(gfilter.height)
    .dimension(dimNumeric)
    .group(countGroup)
    .x(d3.scale.linear().domain([min - lastBarSize, max + lastBarSize]).rangeRound([0, 500]))
    .elasticY(true);
barChart.yAxis().ticks(2);