Flatten an Object hierarchy created with d3.js nesting

I am trying to visualize team collaboration data, in a way like this:

显示每个团队和每周的不同协作工件类型的份额的图表

Different colors in the chart are different collaboration artifact types.

The data from the source looks like this:

var json = [
    {
        "teamLabel": "Team 1",
        "created_date": "2013-01-09",
        "typeLabel": "Email"
        "count": "5"
    },
    {
        "teamLabel": "Team 1",
        "created_date": "2013-01-10",
        "typeLabel": "Email"
        "count": "7"
    },
    /* and of course, a lot more data of this kind */
]

Note that the data is given for single days. So for the above visualization, I need to aggregate the data based on the week of year first. The team name and the artifact type need to be preserved though and are used as grouping attributes. Here's the code:

// "2013-01-09"
var dateFormat = d3.time.format.utc("%Y-%m-%d");

// "2013-02" for the 2nd week of the year
var yearWeek = d3.time.format.utc("%Y-%W");

var data = d3.nest().key(function(d) {
        return d.teamLabel;
    }).key(function(d) {
        var created_date = dateFormat.parse(d.created_date);
        return yearWeek(created_date);
    })
    .key(function(d) {
        return d.typeLabel;
    }).rollup(function(leaves) {
        return d3.sum(leaves, function(d) {
                return parseInt(d.count);    // parse the integer
            });
        }
    )
    .map(json);

This results in an Object hierarchy based on the nesting keys. I do not see how to create the above chart from this, so I am rather looking for a way to convert data into the following structure:

[
    // This list contains an element for each donut
    {
        "teamLabel": "Team 1",
        "createdWeek": "2013-02",
        "values": [
            // This list contains one element for each type we found
            {
                "typeLabel": "Email",
                "count": 12
            },
            {
            ...
            }
        ]
    },
    {
    ...
    }
]

This way, I can use createdWeek and teamLabel for the positioning on x- and y-Axis respectively, and the information under values can be passed to d3.layout.pie() .

Is there a clean way to do this data transformation? If you need any clarification or further details, please let me know.


That's how you do it:

var flat = data.entries().map(function(d){
    return d.value.entries().map(function(e){
        return {
            "teamLabel": d.key,
            "createdWeek": e.key,
            "values": e.value.entries().map(function(f){
                return {"typeLabel": f.key, "count": f.value}
            })
        }
    })
}).reduce(function(d1,d2){ return d1.concat(d2) },[]);

Note that I'm using d3.map instead of the standard javascript object in order to use the map.entries() helper function. I imagine that's what you tried judging by the fact that you're using:

.map(json); // whereas I used .map(json, d3.map)

instead of

.entries(json);

jsFiddle link here:

http://jsfiddle.net/RFontana/KhX2n/

链接地址: http://www.djcxy.com/p/11718.html

上一篇: RNCryptor不能使用JSON字符串

下一篇: 拼合用d3.js嵌套创建的对象层次结构