我在jsfiddle上有以下示例:https://jsfiddle.net/woolycew65/bp5eavxy/我很好奇我是否可以选择饼图片TP-0和TP-2来表示找到时间点0和时间点2的患者,而不是0或2
数据集的示例如下所示:
First win count: 23182, percentage: 2,3182
Second win count: 976818, percentage: 97,6818
Avg sync diff: 128ns
我希望生成的交叉过滤器能够产生" AAA" (2)," BBB" (0)因为现场AAA(101和102)有两名患者的时间点为0 AND 2,而且BBB患者没有符合交叉口过滤标准的患者。
显然,生成的数据集返回" AAA" (4)," BBB" (2)因为现场AAA(101,102,104和105)有四名患者的时间点为0 OR 2,而两名患者在BB部位符合联合过滤标准。
如果通过crossfilter无法实现,那么我假设我需要在tpPie图表上捕获一些事件并执行我自己的过滤,然后使用新数据重新填充crossfilter。
任何帮助都将不胜感激。
答案 0 :(得分:2)
感谢@EthanJewett在上述评论中的评论和crossfilter示例。我一直在寻找这个并且持续了好几个月,最后决定专心专心寻找答案。 @Gordon你可能也对这个例子感兴趣。
我已经能够组合最终的dc.js和crossfilter example,您可以根据交叉点(和)或联合(或强>)。
如果您选择TP-6和TP-8并在或 / 和之间切换,您可以看到它有效。 和选项表示我正在寻找时间点为6和8的患者。
我在数据集中添加了另一个字段“Gender”和另一个网站“CCC”。
根据Ethan的指导,我缺少的关键部分是定义一个额外的维度,当时间点饼图作为交集开始过滤时将被过滤(和)。
时间点饼图尺寸定义如下。真正的参数让维度知道数据是一个数组:
let tpDimension = ndx.dimension(function (d) {return d.timepoints;}, true);
额外的维度也定义如上,除了我们没有分解数组,因此不传递true参数。此维度仅用于时间点饼图filterHandler。
let tp2Dimension = ndx.dimension(function (d) {return d.timepoints;});
如果用户选择了和选项,则会覆盖时间点饼图过滤器处理程序以使用额外维度。
tpPie.filterHandler(function (dimension, filters) {
if (filters.length === 0) {
// the empty case (no filtering)
dimension.filter(null);
} else if (filters.length === 1 && !filters[0].isFiltered) {
// single value and not a function-based filter
dimension.filterExact(filters[0]);
} else if (filters.length === 1 && filters[0].filterType === 'RangedFilter') {
// single range-based filter
dimension.filterRange(filters[0]);
} else {
// an array of values, or an array of filter objects
dimension.filterFunction(function (d) {
for (var i = 0; i < filters.length; i++) {
var filter = filters[i];
if (filter.isFiltered && filter.isFiltered(d)) {
return true;
} else if (filter <= d && filter >= d) {
return true;
}
}
return false;
});
};
// -------------------------------------------------------------
// Custom code to handle intersection filtering (AND)
if (glbTpFilterOption === 'tpAND') {
tpIntersectFilter(filters);
}
return filters;
});
执行时间点相交滤波器的实际代码是:
function tpIntersectFilter(filters) {
if (filters.length === 1) {
// Do not perform the intersect test when only 1 filter selected
tp2Dimension.filterAll();
} else if (filters.length === 0) {
// Since nothing is filtered we need to perform an intersect
// based on all keys.
tp2Dimension.filter(function (d) {
uniqueObjs = tpGroup.all();
for (var i = 0; i < uniqueObjs.length; i++) {
if (d.indexOf(uniqueObjs[i].key) == -1) return false;
}
return true;
});
} else {
tp2Dimension.filter(function (d) {
// Since we are looking for the intersection, test all
// filters, but once there isn't a match get out.
for (var i = 0; i < filters.length; i++) {
if (d.indexOf(filters[i]) == -1) return false;
}
return true;
});
}
}
最后,当用户在选项之间切换时,我需要处理:
$('#tpFilterOptions a').on('click', function () {
var sel = $(this).data('title');
var tog = $(this).data('toggle');
$('#' + tog).prop('value', sel);
$('a[data-toggle="' + tog + '"]').not('[data-title="' + sel + '"]').removeClass('active').addClass('notActive');
$('a[data-toggle="' + tog + '"][data-title="' + sel + '"]').removeClass('notActive').addClass('active');
glbTpFilterOption = sel;
if (sel === "tpOR") {
tp2Dimension.filterAll();
} else {
tpIntersectFilter(tpPie.filters());
}
dc.redrawAll();
})