2015-03-04 1 views
3

Я изо всех сил пытаюсь настроить группы перекрестных фильтров правильно. Может, кто-то может бросить намек!dc.js и crossfilter уменьшают средние значения в день недели

Моя структура данных выглядит более или менее так:

{datetime: "2014-01-01 20:00:00", id:1} 
{datetime: "2014-01-01 22:21:08", id:2} 
{datetime: "2014-01-02 12:00:23", id:3} etc... 

Размерность на DateTime, чтобы вернуться на следующий день недели:

var weekdayDimension = ndx.dimension(function(d) { 
    return new Date(d.datetime).getDay(); 
}); 

Теперь у меня есть проблемы с группировкой. Я хочу, чтобы среднее количество событий в будний день. До сих пор у меня есть (конечно, не правильно)

var weekdayAvgGroup = weekdayDimension.group(function (d) { 
    return d; 
}); 

Я думаю, что я не понимаю, что это группировка делает точно ...

Моя цель должна иметь какой-то график, как:

Monday => Average 40.3 Events 
Tuesday => Average 35.4 Events 

Я создал JSFiddle, пожалуйста, взгляните.

Может кто-нибудь подскакивать, пожалуйста?

UPDATE:

После дополнительного мышления я мог бы создать измерение по дате. Все, что я должен был бы сделать, это знать количество дней, выбранное для того, чтобы высчитать

(total amount of events selected/number of selected days) 

Так мне нужно подсчитать количество групп по размеру даты. Но не нашли решения на этом.

Спасибо

+0

Если вы используете только DateTime, единственное, что вы можете вычислить это счетчик (в неделю, в будние дни, в месяц, в год и т. д.). Вы не можете вычислить среднее значение. –

+0

После небольшого размышления: единственное, что мне понадобится, - это количество выбранных дней. Разве это не так? Так что, если бы я создал измерение на дату, как мне получить количество выбранных дней ... – flightsearch

+0

Все еще недостаточно ясно для меня, я боюсь:/Возможно, объясните из данных, как вы добираетесь до 40.3 и 35.4 –

ответ

4

аннотированный фондовый пример показывает, как сделать средние: http://dc-js.github.io/dc.js/docs/stock.html

В основном вы будете использовать пользовательские уменьшить функцию, поддерживать количество и сумму, и разделить сумму на число (если число больше нуля), чтобы получить среднее значение.

Reductio также делает это довольно легко: https://github.com/esjewett/reductio

EDIT: Оглядываясь назад на это, я заметил, что вы имеете в виду среднее агрегированных подсчетов, через уникальные даты для каждого дня недели.

Я знаю, что уже слишком поздно, но поскольку мы получаем довольно много таких вопросов «агрегирования второго уровня», я думал, что отвечу на этот вопрос, если это поможет кому-то другому.

Таким образом, наши результаты должны бен данные по дням недели, так что мы создали наше измерение и группы соответственно:

// dimension on day of week 
var dim1 = ndx.dimension(function(d) { 
    return d[0].getDay(); 
}); 
// group on day of week 
var grp1 = dim1.group().reduce(
    ... // what goes here? 
); 

Но как мы делаем агрегацию на втором уровне? Эффективно работает уже Crossfilter, чтобы дать все записи за каждый день недели. Нам нужно подсчитывать записи за уникальную дату.

Для этого мы можем использовать d3.map.Сначала мы будем использовать d3.time.day, чтобы удалить информацию о времени дня, затем используйте .getTime(), чтобы получить целое число, на которое мы можем индексировать. Тогда d3.map создает «все понедельники», «все по вторникам» закрома:

var grp1 = dim1.group().reduce(
    function(p, v) { // add 
     var day = d3.time.day(v[0]).getTime(); 
     p.map.set(day, p.map.has(day) ? p.map.get(day) + 1 : 1); 
     p.avg = average_map(p.map); 
     return p; 
    }, 
    function(p, v) { // remove 
     var day = d3.time.day(v[0]).getTime(); 
     p.map.set(day, p.map.has(day) ? p.map.get(day) - 1 : 0); 
     p.avg = average_map(p.map); 
     return p; 
    }, 
    function() { // init 
     return {map: d3.map(), avg: 0}; 
    } 
);  

Наконец, мы вычисляем среднее значение всех бункеров в d3.map с этой функцией:

function average_map(m) { 
    var sum = 0; 
    m.forEach(function(k, v) { 
     sum += v; 
    }); 
    return m.size() ? sum/m.size() : 0; 
} 

Это не может быть настолько эффективным, чтобы ходить по d3.map каждый раз, когда добавляется день, поэтому звонок average_map может быть перемещен в valueAccessor, который мы будем использовать в графике. Я оставлю это как упражнение.

Вот скрипка демонстрирует технику: http://jsfiddle.net/gordonwoodhull/0woyhg3n/11/

И приложенное к оригинальной скрипкой: http://jsfiddle.net/gordonwoodhull/pkh03azq/6/