【问题标题】:Using Crossfilter, is it possible to track max/min when grouping?使用 Crossfilter,是否可以在分组时跟踪最大/最小值?
【发布时间】:2012-05-09 03:32:32
【问题描述】:

使用 Crossfilter (https://github.com/square/crossfilter) 时,我指定了在组中添加和删除数据时要使用的函数。跟踪运行平均值相当简单(使用 CoffeeScript):

reduceAdd = (p, v) ->
  ++p.count;
  p.sum += v.digit;
  p

reduceRemove = (p, v) ->
  --p.count;
  p.sum -= v.digit;
  p

reduceInitial = ->
  {
    count: 0
    sum: 0
    average: ->
      return 0 if this.count == 0
      return this.sum / this.count
  }

是否可以跟踪每个组的最大值和最小值?我想不出将所有元素保存在一个巨大的数组中并执行 d3.min / d3.max 的方法。似乎添加/删除数据效率极低。

我还寻找一种方法来告诉 Crossfilter 从头开始​​完全重建组,而不是从现有组中删除项目。如果应用了过滤器,则重置并重建组。没什么明显的。

【问题讨论】:

标签: javascript crossfilter


【解决方案1】:

您可以使用dimension.top(1)dimension.bottom(1) 来检索当前的最小值和最大值。这些方法尊重交叉过滤器上可能处于活动状态的任何过滤器。

【讨论】:

  • 如何使用 dimension.top 和 dimension.bottom 来获得每组的最大值和最小值?
【解决方案2】:

我想出的最佳解决方案是跟踪有序列表中的所有值,并使用简单的快速排序样式插入函数添加元素(cp.how to insert a number into a sorted array)并使用 indexOf 删除它们。

常用功能:

function insertElement(element, array) {
    array.splice(locationOfElement(element, array) + 1, 0, element);
    return array;
}

function removeElement(element, array) {
    var index = array.indexOf(element);
    if (index >= 0) array.splice(index, 1);
    return array;
}

function locationOfElement(element, array, start, end) {
    start = start || 0;
    end = end || array.length;
    var pivot = parseInt(start + (end - start) / 2, 10);
    if (array[pivot] === element) return pivot;
    if (end - start <= 1)
        return array[pivot] > element ? pivot - 1 : pivot;
    if (array[pivot] < element) {
        return locationOfElement(element, array, pivot, end);
    } else {
        return locationOfElement(element, array, start, pivot);
    }
}

function maxElement(array) {
    return (array.length > 0) ? 
        array[array.length - 1] : null;
}

function minElement(array) {
    return (array.length > 0) ? 
        array[0] : null;
}

在组中添加和删除数据以跟踪最小值/最大值时使用的函数:

minMaxDimension = cf.dimension(function (d) {
    return d.key; 
});

var reduceAdd = function(p, v) {
    insertElement(v.value, p.elements);
    return p;
};

var reduceRemove = function(p, v) {
    removeElement(v.value, p.elements);
    return p;
};

var reduceInitial = function() {
    return { 
        elements: [],
        max: function() { return maxElement(elements); },
        min: function() { return minElement(elements); }
    }
}

minMaxGroup = minMaxDimension
    .group()
    .reduce(reduceAdd, reduceRemove, reduceInitial)
    .orderNatural()
    .top(Infinity);

【讨论】:

  • 这是迄今为止更有效的解决方案。
  • 我觉得你可以用d3.bisectRight代替locationOfElement
【解决方案3】:

玩了一会儿之后,你可以通过再次调用 group 方法来重建组。

【讨论】:

  • 有趣,我会检查一下。顺便说一句,如果没有更多的声誉,我无法在 SO 中制作“crossfilter”标签。如果有人偶然发现并可以创建标签,我很乐意重新标记我的问题。
  • 刚刚创建了标签。 Crossfilter 是一个很棒的库,希望它会得到更多的关注。
  • 您能否更详细地解释一下解决方案?您何时/如何重建小组?
猜你喜欢
  • 2022-01-20
  • 1970-01-01
  • 1970-01-01
  • 2012-07-19
  • 1970-01-01
  • 1970-01-01
  • 2021-06-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多