问题描述
我在jsfiddle上有以下示例:很好奇我是否可以选择饼状切片TP-0和TP-2来表示同时具有时间点0和时间点2,而不是0或2的患者。
I have the following example on jsfiddle: https://jsfiddle.net/woolycew65/bp5eavxy/ and am curious if I can select pie slices TP-0 and TP-2 to mean find the patients that have both timepoint 0 and timepoint 2, not 0 or 2.
数据集的示例如下所示:
A sample of the dataset is shown below:
let data = [
{patientId: 101, site: "AAA", timepoints: [0, 2, 4, 6, 8, 12, 18, 24]},
{patientId: 102, site: "AAA", timepoints: [0, 2, 4, 6]},
{patientId: 103, site: "AAA", timepoints: [8, 12, 18, 24]},
{patientId: 104, site: "AAA", timepoints: [0, 4, 8, 18]},
{patientId: 105, site: "AAA", timepoints: [2, 6, 12, 24]},
{patientId: 501, site: "BBB", timepoints: [0]},
{patientId: 502, site: "BBB", timepoints: [2]},
{patientId: 503, site: "BBB", timepoints: [4]},
{patientId: 504, site: "BBB", timepoints: [6]},
{patientId: 505, site: "BBB", timepoints: [8]},
{patientId: 506, site: "BBB", timepoints: [12]},
{patientId: 507, site: "BBB", timepoints: [18]},
{patientId: 508, site: "BBB", timepoints: [24]}
];
我希望生成的交集过滤器产生 AAA(2), BBB(0 ),因为在AAA站点(101和102)有两名患者的时间点为0 和 2,在BBB站点没有患者满足交叉点过滤条件。
I would like the resulting intersection filter to produce "AAA" (2), "BBB" (0) since there are two patients at site AAA (101 and 102) that have timepoints 0 AND 2 and no patients at site BBB that meet the intersection filter criteria.
很明显,结果数据集返回 AAA(4), BBB(2),因为站点AAA上有四名患者(101、102、104和105)的时间点为0 OR 2名和两名BB病房的患者符合联合过滤器标准。
Obviously the resulting dataset returns "AAA" (4), "BBB" (2) since there are four patients at site AAA (101, 102, 104, and 105) that have timepoints 0 OR 2 and two patients at site BB that meet the union filter criteria.
如果无法通过交叉过滤器,那么我想我需要捕获一些事件tpPie图表并执行我自己的过滤,然后使用新数据重新填充交叉过滤器。
If it is not possible via crossfilter then I assume I need to capture some event on the tpPie chart and perform my own filtering and then re-populate crossfilter with the new data.
任何帮助将不胜感激。
推荐答案
感谢@EthanJewett提供上述注释中的注释和交叉过滤器示例。我已经不停地寻找这个问题了好几个月,最终决定专心寻找答案。 @gordon您可能对此示例也有兴趣。
Thank you @EthanJewett for the comments and crossfilter example in the above comments. I have been search for this off and on for many months and finally decided to concentrate exclusive to find the answer. @Gordon you might also be interested in this example.
我已经能够将最终的dc.js和交叉过滤器放在一起,您可以选择根据交集(和)或并集(或)。
I have been able to put together a final dc.js and crossfilter example where you can choose to filter the timepoints based on an intersection (and) or a union (or).
如果选择TP-6和TP-8并在或 / 和之间进行切换,则可以看到它正常工作。 和选项表示我正在寻找时间点为6和8的患者。
If you select TP-6 and TP-8 and switch between or / and you can see it work. The and option is saying that I am looking for patients that have timepoints at 6 and 8.
我添加了一个附加字段性别
I have added an additional field "Gender" and another site "CCC" to the dataset.
根据Ethan的指导,我缺少的关键部分是定义了一个附加维度,该维度将在时间点饼图时进行过滤开始过滤为交集(和)。
Based on Ethan's guidance the key part that I was missing was defining an additional dimension that will be filtered when the timepoint pie chart is begin filtered as an intersection (and).
时间点饼图的尺寸定义如下。 true参数使维度知道数据是数组:
The timepoint pie chart dimension is defined below. The true argument lets the dimension know that the data is an array:
let tpDimension = ndx.dimension(function (d) {return d.timepoints;}, true);
额外维度也如上定义,只是我们不分解数组,因此为真参数没有通过。此维度仅在时间点饼图filterHandler中使用。
The extra dimension is also defined as above except we do not break out the array, thus the true argument is not passed. This dimension is only used in the timepoint pie chart 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;
});
执行时间点相交过滤器的实际代码为:
The actual code to perform the timepoint intersect filter is:
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();
})
这篇关于我可以基于crossfilter / dc.js中的交集(和)来过滤数据吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!