#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. конечно, я упростил логику и добавил некоторые пояснения.