我可以根据crossfilter / dc.js中的交叉点(和)过滤数据吗?

时间:2017-08-03 14:29:56

标签: dc.js crossfilter

我在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。

任何帮助都将不胜感激。

1 个答案:

答案 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();

})