11

我正在为时间报告应用程序开发 d3.js 可视化。我在包含项目时间报告(简化)的数组实际中有行数据:

[{  resource: "John Smith",
    reporting_period: "2012/04/1",
    project: "Java implementation",
    hours: 8} 
 ... }]

我正在尝试使用d3.nest运算符按项目、资源和期间对项目实际值进行分层分组。一切都很好,但我找不到使用nest.rollup()运算符在分组的中间级别获取小时小计的方法。

我有类似的东西:

actuals_by_prj_rsrc_period = d3.nest()
        .key(function(d) { return d["project"]; })
        .key(function(d) { return d["resource"]; })
        .key(function(d) { return d["reporting_period"]; })
        .rollup(function(rows) {return {
            tot_hours:d3.sum(rows, function(d) {return d["hours"];}),
            actuals: rows
        };})
        .entries(actuals);

但它仅在叶级别返回tot_hours 。关于如何仅使用d3.nest解决此问题的任何建议?

4

1 回答 1

6

来自文档:

嵌套汇总(函数)

指定要应用于每组 元素的汇总函数。汇总函数的返回值将替换映射运算符返回的关联数组或条目运算符返回的每个条目的值属性中的叶值数组。

如您所见,汇总适用于叶元素。您可以通过将数据嵌套在多个级别来绕过此问题:

function nest(keys, data, rollupFunc) {
    var nst = d3.nest();
    keys.forEach(function(key) {
        nst.key(function(d) { return d[key]; });
    });
    if (rollupFunc) {
        nst.rollup(rollupFunc);
    }
    return nst.entries(data);
}

var rollupFunction = function(d) {
    return {
        "total_hours": d3.sum(d, function(dd) { return dd["hours"]})
    }
}

var rez1 = nest(["project", "resource"], actuals);
var rez2 = nest(["project"], actuals, rollupFunction);
var rez3 = nest(["project", "resource"], actuals, rollupFunction);

但这对于较大的数据集非常低效。否则我会建议使用nest()函数来创建所有中间级别。然后,您可以使用自己的递归函数汇总总小时数。伪代码:

function aggregate(node) {
    if (node has property total_hours) {
        return total_hours
    }
    sum = 0
    foreach child in data.values {
        sum += aggregate(child)    
    }
    node.total_hours = sum
    return node.total_hours 
}
于 2015-07-21T22:59:22.890 回答