Заполнение пробелов в гнезде D3

У меня есть массив или объекты, состоящие из даты и некоторых значений:

var flatData = [
    { "date": "2012-05-26", "product": "apple"  },
    { "date": "2012-07-03", "product": "orange" },
    ...
]

Я пытаюсь использовать d3.nest() для получения количества этих объектов по годам, а затем по месяцам.

var nestedData = d3.nest()
    .key(function(d) { return d.date.split('-')[0]; })  // key is the year
    .sortKeys(d3.ascending)
    .key(function(d) {
        var splitDate = d.date.split('-');
        return splitDate[0] + '-' + splitDate[1]; // key is year-month
    })
    .sortKeys(d3.ascending)
    .rollup(function(d) {
        return d.length;
    })
    .entries(flatData);

Это почти работает, за исключением того, что, когда в течение месяца нет объектов, вложенные данные не содержат записей, указывающих число 0 за этот месяц. Есть ли уловка, чтобы рассказать D3 о заполнении этих пробелов?

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

Ответ 1

Попробуйте добавить отсутствующие точки данных после сокращения:

var flatData = [
    { "date": "2012-05-26", "product": "apple"  },
    { "date": "2012-07-03", "product": "orange" }]

nestedData = d3.nest()
    .key(function(d) { return d.date.split('-')[0]; })  // key is the year
    .sortKeys(d3.ascending)
    .key(function(d) {
        var splitDate = d.date.split('-');
        return splitDate[0] + '-' + splitDate[1]; // key is year-month
    })
    .sortKeys(d3.ascending)
    .rollup(function(d) {
        return d.length;
    })
    .entries(flatData);


yMFormat = d3.time.format('%Y-%m')

makeAllKeys = function(year) {
    allKeys = [];
    for(var i = 0; i<12;i++) {  // 12 months in a year
        allKeys.push(yMFormat(new Date(year,i,1)));
    }
    return allKeys;
}

nestedData = nestedData.map(function(yearObj) {
    return {
        values: makeAllKeys(+yearObj.key).map(function(k) { 
                value = yearObj.values.filter(function(v) { return v.key == k; })[0];
                return value || ({key: k, values: 0});
            })
    };
});