【问题标题】:General reduceInitial function crossfilter一般reduceInitial函数crossfilter
【发布时间】:2018-05-02 06:07:49
【问题描述】:

我正在构建一个 dc.js / d3.js 仪表板,我经常需要在其中创建包含每个键的数量和每个键的总值百分比的交叉过滤器组。这就是为什么我要制作通用的 reduceAdd、reduceRemove 和 reduceInitial 函数。我设法做了前 2 个,但我不明白 reduceInitial 行为:

function reduceAdd(dim,grouping,col) {
    var keys = getKeys(dim); // get the keys name in an array of string
    return function(p,v) {
        p.total += parseInt(v[col]); // get the running total
        for (var i = 0; i < keys.length; i++) {
            if(v[grouping] == keys[i]) {p[keys[i]] += +v[col];}
            p[keys[i]+"perc"] = p[keys[i]]/p.total; // calculate a percentage for ech key
        }
        return p;
    }
}

function reduceRemove(dim,grouping,col) {
    var keys = getKeys(dim);
    return function(p,v) {
        p.total -= parseInt(v[col]);
        for (var i = 0; i < keys.length; i++) {
            if(v[grouping] == keys[i]) {p[keys[i]] -= +v[col];}
            p[keys[i]+"perc"] = p[keys[i]]/p.total;
        }
        return p;
    }
}

这是工作的非通用function reduceInitFC() { return {total:0, LILOU:0, MARIUS:0,ORIANE:0,LILOUperc:0,MARIUSperc:0,ORIANEperc:0}; }

这是我尝试过的:

function reduceInit(dim) { 
    var keys = getKeys(dim);
    var initArray= {};
    initArray["total"] = 0;
    for (var i = 0; i < keys.length; i++) {
        initArray[keys[i]] = 0;
        initArray[keys[i]+"perc"] = 0;
    }
    console.log(initArray); // (1)
    console.log({total:0, LILOU:0, MARIUS:0,ORIANE:0,LILOUperc:0,MARIUSperc:0,ORIANEperc:0});
    return function() {
            return initArray; 

    }   
}

结果是: (1) 每两次迭代的所有键的输出都为 0,而其他迭代的一些非零值 当我使用此函数时,组中的结果值与键保持不变,实际上并非如此,当我手写零值时也不是这样。

如果有人可以提供帮助,那将是超级友好和有用的。

最好, 西奥

【问题讨论】:

  • 什么是getKeys?您可以发布一个工作示例吗?我怀疑像这样使用getKeys 会导致reduceAddreduceRemove 中出现您没有意识到的错误,并且在reduceInit 中还没有任何键,因此您不会得到任何值,但是如果没有一个工作示例,我就无法知道getKeys 做了什么以及创建组的确切时间。
  • 啊,我收回关于getKeys 引入错误的说法。虽然添加新数据时它不会更新,但这实际上很好。如果它确实更新了,您将有错误。无论如何,仍然需要一个工作示例才能有很大的机会诊断问题。
  • 我可能会添加一个小提琴,但这需要一些时间,顺便说一句,这是我的 getKey 函数,它只是返回一个包含一个维度的所有键的数组:
  • function getKeys(dim) { var len = dim.group().all().length; var keys = []; for (var i = 0; i &lt; len; i++) { keys[i] = dim.group().all()[i].key; } return keys; }

标签: javascript d3.js dc.js crossfilter


【解决方案1】:

我认为您的 reduceInit 看起来不错,但我认为这不可能通过 reduce 实现。 reduce 增量计算总计 - 直到组遍历维度中的所有行才有意义。因此,在 reduce 完成之前,无法计算每个键的百分比。 (同样,虽然 reduce 可用于计算单个键值的平均值,但它们不能用于所有键的平均值,因为这将取决于减少的总数。)(已更新,另请参阅此答案的cmets)

但是由于您已经有了减少的总数和键/类别的总数,您可以在图表的 valueAccessor 中计算百分比。

function valueAccessor(d){
  return d.value[keyName] / d.value.total
}

【讨论】:

  • 也许我说错了,我唯一的问题是概括 reduceInital。当我使用只返回硬编码 0 值的 reduceInitial 函数时,计算效果很好:)
  • 这是正确的 - 您应该在 valueAccessor 中计算平均值,而不是在减速器中,主要是出于性能原因。
  • 哦,我不知道 Ethan,你能解释一下它是如何影响性能的吗?谢谢你们俩的帮助!
  • reduce 函数针对添加的每条记录以及进出过滤器的每条记录运行。平均值只需要在你想显示它的时候计算,所以不需要重复计算,也不应该进入减速器。在reduceAdd 函数中添加console.log,您会看到它被调用的频率。
  • 但是当我们在group函数中计算的时候,在后台是不是也发生了同样的事情呢?
猜你喜欢
  • 2010-11-03
  • 2014-08-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-05-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多