If you are working with D3, there is a good chance that you will want to nest data. Getting your data into common D3 formats is often half the battle when working with D3, so you really want to have a number of tools that transform your data into these common formats. For nesting, there are two tools that I am familiar with. The first is D3.nest(). Let’s say our data is an array of objects like this:
We can easily nest that using D3.nest() like so:
The result is a hierarchical nest of data objects. Each branch node has a key property specifying the name of the branch, and a values property specifying one or more child nodes. Leaf nodes contain the original keys and values for each data item that was passed to the nest method.
The second tool is Underscore.nest(). In similar fashion, we can nest our data like so:
The result again is a hierarchical data structure, but this time one that is based on name and children. Each branch node has a name property, specifying its name and a children property, specifying one or more child nodes. Leaf nodes again contain the original keys and values for each data item. Note that the name and children format of Underscore.nest() matches the flare.json format used in many of the D3 examples.
So far so good with D3.nest() and Underscore.nest(). Let’s try something else. What if our data has arbitrary depth like so:
D3.nest() gives us this:
and Underscore.nest() gives us this:
Now we have a problem. Both D3.nest() and Underscore.nest() try to access keys that are undefined, and go on to create branch nodes with name undefined. They are both assuming that our data has uniform depth. However we don’t want undefined branches - we want the nesting to stop at leaf nodes, wherever they may be.
So, how do we nest data of arbitrary depth? Someone pointed me towards a function called burrow.js that does exactly that.
In my case, I am nesting data for something similar to D3’s Zoomable Treemap Example so I ended up modifying it to fit that case. I’ve named the result Underscore.burrow. I have annotated the source below:
So, if your data looks like this:
You can make it look like this with Underscore.burrow:
Now we have nested data with branches and leaves at arbitrary depths! Underscore.burrow can take an an array of objects or an array of arrays. If you pass an array of objects, each object must contain a nodes property, whose value is an array of node items. Likewise, if you pass an array of arrays, each array must be a list of node items. In both cases, each node item will become a branch node with the exception of the last node item which will become the leaf node. If you pass an array of objects, there is an additional option of including extra data at each leaf item, via the leafData property like below. The leafData property can be either a string or an object.
The code for Underscore.burrow as well as more documentation can be found here. As I noted at the top of this post, getting your data into a common D3 format can be a large part of the battle when working with D3. It took me a lot longer than I would have liked to figure out how to nest data of arbitrary depth. We really need a number of off the shelf tools like D3.nest, Underscore.nest, burrow.js and Underscore.burrow that will help us quickly get our data into common D3 formats.