Столбчатые диаграммы с перекрестным фильтром сводят на нет значения

#dc.js #crossfilter

#dc.js #перекрестный фильтр

Вопрос:

Я использую crossfilter2 с dcv3

Мои данные находятся в формате csv, который я загрузил в память

Исходные данные

 Day, ID
1, 2
1, 2
1, 2
2, 5
3, 6
4, 6 
  

Обработанные данные

 Day, ID, target
1, 2, True
1, 2, True
1, 2, True
2, 5, False
3, 6, False
4, 6, False 
  

В настоящее время то, что я пытаюсь сделать, это создать столбчатую диаграмму с перекрестным фильтром с двумя столбцами. Если ID == 2 , я рассматриваю это как одну группу и ID !=2 как другую группу. Однако я не могу сделать это динамически в DC / crossfilter, что приводит к необходимости предварительной обработки данных для добавления нового столбца и обработки столбца, как показано в моем решении ниже.

Есть ли способ лучше?

 var dimID = ndx.dimension(function(d) { return d.day; });

var id_stacked = dimID.group().reduce(
function reduceAdd(p, v) {
    p[v.target] = (p[v.target] || 0)   1;
    return p;
},
function reduceRemove(p, v) {
    p[v.target] = (p[v.target] || 0) - 1;
    return p;
},
function reduceInitial() {
    return {};
    });

//Doing the stacked bar chart here
stackedBarChart.width(1500)
.height(150)
.margins({top: 10, right: 10, bottom: 50, left: 40})
.dimension(dimID)
.group(id_stacked, 'Others', sel_stack("True"))
.stack(id_stacked, 'Eeid of interest', sel_stack("False"))
  

Это моя функция sel_stack

 function sel_stack(i) {
    return function(d) {
        return d.value[i] ? d.value[i] : 0;

    };
}
  

Я строю столбчатую диаграмму, ось x которой соответствует дню, а ось Y — частоте ID == 2 или ID!=2 в столбчатой диаграмме с накоплением

Ответ №1:

Итак, вы хотите сгруппировать по дням, а затем сложить по тому, ID===2 . Хотя dc.js будут принимать множество различных форматов, часто хитрость заключается в придании данным правильной формы.

Вы на правильном пути, но вам не нужен дополнительный столбец, чтобы создавать стеки для «равно 2» и «не 2». Вы можете вычислить это напрямую:

 var dayDimension = ndx.dimension(function(d) { return d.Day; }),
    idStackGroup = dayDimension.group().reduce(
        function add(p, v) {
              p[v.ID===2 ? 'is2' : 'not2'];
            return p;
        },
        function remove(p, v) {
            --p[v.ID===2 ? 'is2' : 'not2'];
            return p;
        },
        function init() {
              return {is2: 0, not2: 0};
        });
  

Это стандартные функции добавления / удаления для уменьшения нескольких значений для каждой ячейки. Вы найдете другие варианты, в которых название поля определяется данными. Но здесь мы знаем, какие поля будут существовать, поэтому мы можем инициализировать их равными нулю в init и не беспокоиться о появлении новых полей.

add Функция вызывается, когда строка добавляется в перекрестный фильтр или фильтр изменяется таким образом, что строка включается; remove функция вызывается всякий раз, когда строка отфильтровывается или удаляется из crossfilter. Поскольку мы не беспокоимся о undefined (1), мы можем просто увеличивать ( ) и уменьшать ( -- ) значения.

Наконец, нам нужны средства доступа, чтобы извлекать эти значения из объекта. Я думаю, что проще встроить средства доступа к стеку — sel_stack был написан для добавления динамического количества стеков. (YMMV)

   .group(idStackGroup, 'Others', d => d.value.not2)
  .stack(idStackGroup, 'Eeid of interest', d => d.value.is2);
  

два / не два стека

https://jsfiddle.net/gordonwoodhull/fu4w96Lh/23/

(1) Если вы выполняете какую-либо арифметику, undefined это приводит к NaN и NaN разрушению всех дальнейших вычислений.

Комментарии:

1. вы не могли бы лучше объяснить свой код? особенно в функциях добавления и удаления? например, что делает —p? и зачем это нужно

2. конечно, я упростил логику и добавил некоторые пояснения.