D3.js: A D3 snippet, to convert JSON of force layout into of hierarchy layout.

D3,js is great library to create data visualization project, but some built-in apis need different data structure. Especially hierarchy and force layout have incompatible data structure and identifier to make it. But today, during testing visualization project, I needed to make those two layout from the same JSON file. Then I made a snippet for this, you can see this at the bottom of the post.

Hierarchy layout, which props cluster, pack, partition, tree and treemap, needs “name” and “children” identifier. So I have my own JSON file with name and children like this:


{
"name": "罪",
"children": [
{
"name": "強盗",
"総 数": "2474",
"犯罪供用物あり": "1249",
"犯罪供用物なし": "1225",
"けん銃": "2",
"ライフル銃": "0",
"散弾銃": "0",
"空気銃": "1",
"その他の銃砲": "3",
"children": [
{
"name": "強盗殺人",
"総 数": "29",
"犯罪供用物あり": "24",
"犯罪供用物なし": "5",
"けん銃": "1",
"ライフル銃": "0",
"散弾銃": "0",
"空気銃": "0",
"その他の銃砲": "0"
},
......

<span style="line-height: 1.5em;">

We can call “hierarchy()” to make hierarchy layout, but I wanted to make force layout from the same JSON file as well, with nothing to change the file.

Force layout needs “nodes” and “links” key, in addition, links keys must have source and target key. Source and target keys take indices of each node; It is the threshold of inconvenience. Anyway for example, it is like that;


{
"nodes":[
{"name":"罪","group":1},
{"name":"強盗","group":1},
{"name":"傷害","group":1}

.....

],
"links":[
{"source":1,"target":0,"value":1},
{"source":2,"target":0,"value":8},
{"source":3,"target":0,"value":10},
{"source":3,"target":2,"value":6}
......

]
}

<span style="line-height: 1.5em;">

After all, I wanted to make those structure from the upper JSON file. Yes, I made such a snippet of function:


function HierarchyToForcelayout(root,groups,values){

//Change if you want.
groups = groups || "depth";
values = values || "size";

// Make ierarchy structure.
var test = hierarchy(root);

var forcejson = { "nodes": [], "links": []};

//Get index for links target and source.
var name_index = {};
test.forEach(function(d,i){

name_index[d.name] = i;

});

// Construct nodes and links for force layout.
test.forEach(function(d,i) {
var temp_node = {name: d.name, group: d[groups]};

&nbsp;

forcejson.nodes.push(temp_node);

if(d.children) {
d.children.forEach(function(c){
var temp_link = {source: i, target:name_index[c.name], value:c[values]};

&nbsp;

forcejson.links.push(temp_link);
})
}
});

return forcejson;

};

<span style="line-height: 1.5em;">

But if anyone knows other solutions or API which is nicer than mine, I’m pleased to know.

Leave a Reply