Javascript 如何在crossfilter中的平面数据中进行group.reduce

Javascript 如何在crossfilter中的平面数据中进行group.reduce,javascript,mapreduce,crossfilter,dc.js,Javascript,Mapreduce,Crossfilter,Dc.js,新的交叉过滤。我有一个平面数据,如下所示: id,name,patientId,conditionId,isPrimary,age,gender,race,Status,CGI 1,M1,1,c1,Y,33,Male,White,Discharged,0 2,M2,1,c1,N,33,Male,White,Discharged,0 3,M3,1,c2,N,33,Male,White,Discharged,0 4,M4,1,c2,N,33,Male,White,Discharged,0

新的交叉过滤。我有一个平面数据,如下所示:

 id,name,patientId,conditionId,isPrimary,age,gender,race,Status,CGI
 1,M1,1,c1,Y,33,Male,White,Discharged,0
 2,M2,1,c1,N,33,Male,White,Discharged,0
 3,M3,1,c2,N,33,Male,White,Discharged,0
 4,M4,1,c2,N,33,Male,White,Discharged,0
 5,M5,1,c3,N,33,Male,White,Discharged,0
 6,M6,1,c3,N,33,Male,White,Discharged,0
 25,M1,5,c1,Y,33,Male,White,Discharged,1
 26,M7,5,c2,N,33,Male,White,Discharged,1
 27,M4,5,c4,N,33,Male,White,Discharged,1
 28,M4,5,c1,N,33,Male,White,Discharged,1
 29,M4,5,c2,N,33,Male,White,Discharged,1
 30,M5,5,c4,N,33,Male,White,Discharged,1
 29,M2,6,c1,Y,33,Male,White,Discharged,1
 30,M2,7,c1,Y,33,Male,White,Discharged,1
我想对
conditionId
进行计数,但是由于有多个记录属于由
patientId
标识的同一个人,因此值
c1
的计数应该是4(属于
patientId
1,5,6,7),因为同一个患者可能有多个记录(例如,
patientId
的1重复了6次,其中两个有c1,应该只计算一次)。我正在努力编写一个
组。在
conditionId
上减少
,但甚至无法开始


提前感谢。

这里有一种方法。在示例中,我假设第一个值是
patientId
,第二个值是
conditionId
。代码跟踪已经看到的分组键(将
patientId
conditionId
串联起来),并忽略它们

var countMap = [
    [1, 'c1'],
    [1, 'c1'],
    [2, 'c1'],
    [2, 'c2']
].reduce(function (r, v) {
    var condition = v[1],
        groupKey = v[0] + condition;

    if (!r.seen[groupKey]) {
        r.seen[groupKey] = true; 
        r.count[condition] = (r.count[condition] || 0) + 1;
    }

    return r;

}, {seen: {}, count: {}}).count;


countMap.c1; //2
countMap.c2; //1

我不知道crossfilter或dc.js,这就是为什么我给你一个普通的js解决方案。

在crossfilter中这样做有点复杂,但解决方案与@plalx提供的类似

这是我在我的一个项目中使用的一个帮助函数。它不是完美的,并且经过了一些优化以减少字典查找,因此它不是最具可读性的。基本思想是,您需要为每个组保留一个以前看到的值字典。您只需要记住患者,因为根据您所在的组,情况已经知道在:

function reduceHelper(accessorFunction) {
        var internalCount;
        return {
            add: function (p, v) {
                if(p.unique.has(accessorFunction(v))) {
                    internalCount = p.unique.get(accessorFunction(v));
                    p.unique.set(accessorFunction(v), internalCount + 1);
                } else {
                    p.unique.set(accessorFunction(v), 1);
                    ++p.count;
                }
                return p;
            },
            remove: function (p, v) {
                if(p.unique.has(accessorFunction(v))) {
                    internalCount = p.unique.get(accessorFunction(v));
                    if(internalCount == 1) {
                        p.unique.remove(accessorFunction(v));
                        --p.count;
                    } else {
                        p.unique.set(accessorFunction(v), internalCount - 1);
                    }
                }
                return p;
            },
            init: function () {
                return {unique: d3.map(), count: 0};
            }
        };
    }
您需要在数据上创建一个交叉过滤器(xfilter),然后:

var helperFunctions = reduceHelper(function(d) { return d.patientId; });
var dim = xfilter.dimension(function (d) { return d.conditionId; };
var group = dim.group()
              .reduce(helperFunctions.add, helperFunctions.remove, helperFunctions.init);

现在,您的小组将统计每种情况下的患者数量。如果某个患者的情况出现不止一次,则该患者仍将只统计一次。如果我的解决方案正常工作,至少会这样:-)

您希望的输出是什么?你只是想要c1的计数,还是想要一个包含每个条件计数的映射?我想要conditionId的计数,它应该是c1:4、c2:2、c3:1和c4:1。谢谢,谢谢!你是个天才!:)