I'm trying to create a collapsible tree diagram in D3v4 like this. I have my data as an array of JSON objects and need to prepare the data into a hierarchical tree structure.
My data looks likes this:
[
{
"ingoingBatch": "BC1",
"process": "API",
"outgoingBatch": "CD1",
"counterIndex": "5"
},
{
"ingoingBatch": "BC2",
"process": "API",
"outgoingBatch": "CD1",
"counterIndex": "6"
},
{
"ingoingBatch": "AB1",
"process": "PUR",
"outgoingBatch": "BC1",
"counterIndex": "1"
},
{
"ingoingBatch": "AB2",
"process": "PUR",
"outgoingBatch": "BC1",
"counterIndex": "2"
},
{
"ingoingBatch": "AB3",
"process": "PUR",
"outgoingBatch": "BC2",
"counterIndex": "3"
},
{
"ingoingBatch": "AB4",
"process": "PUR",
"outgoingBatch": "BC2",
"counterIndex": "4"
}
]
The structure I wanted is something like this structure
I have tried making a JSfiddle where you can see the original data on line 129-142. I have inserted my own data on line 11-115 and used the function d3 function nest as found here on line 117-126:
var entries = d3.nest()
.key(function(d) { return d.ingoingBatch; })
.key(function(d) { return d.outgoingBatch; })
.entries(json);
console.log(entries);
var treeData = d3.hierarchy(entries);
console.log(treeData);
I assume the problem is within the data preparation. The error message I get when I run the JSfiddle with my data is:
TypeError: root.children is undefined
The root node should be C1 and the structure should look like this:
C1
B2 B1
A1 A2 A3 A4
The link between the nodes is the ingoingBatch and outgoingBatch. Can anybody please help prepare my data to get my data preparation just right?
-----------UPDATE-----------
If I use the answer from here this question I get a bit closer on having the right data structure. When I instead of this:
var entries = d3.nest()
.key(function(d) { return d.ingoingBatch; })
.key(function(d) { return d.outgoingBatch; })
.entries(json);
console.log(entries);
var treeData = d3.hierarchy(entries);
console.log(treeData);
Use the the answer from the other question and have this function instead:
var newData = { name :"root", children : [] },
levels = ["outgoingBatch"];
// levels = ["ingoingBatch","outgoingBatch"];
// For each data row, loop through the expected levels traversing the output tree
json.forEach(function(d){
// Keep this as a reference to the current level
var depthCursor = newData.children;
// Go down one level at a time
levels.forEach(function( property, depth ){
// Look to see if a branch has already been created
var index;
depthCursor.forEach(function(child,i){
if ( d[property] == child.name ) index = i;
});
// Add a branch if it isn't there
if ( isNaN(index) ) {
depthCursor.push({ name : d[property], children : []});
index = depthCursor.length - 1;
}
// Now reference the new child array as we go deeper into the tree
depthCursor = depthCursor[index].children;
// This is a leaf, so add the last element to the specified branch
if ( depth === levels.length - 1 ) depthCursor.push({ outgoingBatch : d.outgoingBatch });
});
});
var treeData = newData
console.log(treeData);
I get a three diagram out. But it is not structured correctly, since CD1 is not set as the root node but instead one of the children.