crossfilter新手。我有一个平面数据,如下所示:
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,应该只计数一次)。我很难在group.reduce
上写conditionId
,但甚至无法开始。
提前致谢。
答案 0 :(得分:0)
这是一种做法。在示例中,我假设第一个值是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,这就是我给你一个vanilla JS解决方案的原因。
答案 1 :(得分:0)
在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};
}
};
}
您需要在数据上创建一个Crossfilter(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);
您的小组现在将计算每种病情的患者人数。如果某个患者的病情出现不止一次,该患者仍然只会被计算一次。至少,如果我的解决方案正常运行: - )