Treemap

Dataviz logo representing a Tree chart.

A treemap displays a hierarchical dataset (a tree) as a set of rectangles. Rectangle sizes are proportional to their numeric value.

d3.js has some handy functions to compute the rectangle positions. React becomes useful to render those rectangles, animate transitions and more. This post explains how to make those 2 tools work together to build a Treemap component.

Useful links

The Data

The dataset describes a hierarchy using a recursive structure. Each item in this structure is called a node, the lowest nodes of the hierarchy being called leaves.

The dataset is an object that has at least 3 properties: name, value and children.children is an array of nodes that have this structure too.


Here is a minimal example of the data structure:

const data = {
  type: 'node',
  name: "boss",
  value: 2300,
  children: [
    {type: 'leaf', name:"Mark", value: 90},
    {type: 'leaf', name:"Robert", value: 12},
    {type: 'leaf', name:"Emily", value: 34},
    ...
}

It's very likely that your dataset is not formatted as above yet. But don't fret, the next section will teach you how to convert it. ⬇️

Data wrangling

Three main input data formats are usually encountered when it comes to store hierarchical information. It's always a struggle to deal with those various formats:

→ list of connection (csv)

→ list of connection (js object)

→ json with hierarchy

I described in depth how to deal with those format in the dendrogram section of the gallery that shares the same kind of input format. Please take a look there!

Read more

The hierarchy format or "root node"

A treemap is a hierarchical layout. D3.js has a lot of utility functions allowing to deal with this kind of hierarchical data. To use those functions we first need to create a "Root node" or "Hierarchy".

But what the heck is this? 🤔

A "root node" or "hierarchy" is a javascript object. It has almost the same shape as the input data described above. But with some additional properties and methods that will make our life easier.

→ how to build a root node

If your dealing with the format describe in the previous section, you just have to pass it to the d3 hierarchy function:

const hierarchy =  d3.hierarchy(data)

Note that this concept of root node is key for all the charts representing a hierarchy like dendrograms, circle packing, networks and more. Please check the dendrogram page where I explain it in detail.

Read more

Compute rectangle positions with d3.treemap()

From the hierarchy object computed above we need to compute the position of every rectangles of the treemap.

This is possible thanks to the treemap() function of d3.js that can be invoked like this:

const treeGenerator = d3.treemap()
  .size([width, height])
  .padding(4); // space between rectangles

// Use the generator on the hierarchy object built in previous section
const treeLayout =  treeGenerator(hierarchy);

The result is an object that has almost the same shape as the initial hierarchy object. But for each node, an additional x0, x1, y0 and y1 are available. Those are the coordinates of the rectangle in our SVG space! 🔥

Treemap with 1️⃣ level of hierarchy

With the coordinates of each rectangle being available, it is just a matter of looping through all of them and drawing them using SVG.

The leaves() method is usefull to list all leaves, allowing to make the loop easily:

const rects = treeLayout.leaves().map((leaf) => {
  return (
    <g key={leaf.id}>
      <rect
        x={leaf.x0}
        y={leaf.y0}
        width={leaf.x1 - leaf.x0}
        height={leaf.y1 - leaf.y0}
      />
    </g>
  )
}

This results in a first basic treemap 😋

Mark90Robert12Emily34Marion53Nicolas98Malki22Djé12Mélanie45Einstein76

The most basic treemap with 1 level of hierarchy made with react and d3.js.

Treemap with 2️⃣ levels of hierarchy

Treemaps are also handy to display nested data structure. For instance, let's consider a company with a CEO, several teams, and a few employees per team. This result in a structure with several levels of hierarchy.

Pretty much the same strategy is used to draw the treemap. But note that each leaf has a parent property that is very handy to use a categorical color scale to the graph.

// Create a color scale
const firstLevelGroups = hierarchy?.children?.map((child) => child.data.name);
var colorScale = d3
  .scaleOrdinal()
  .domain(firstLevelGroups)
  .range(['red', 'green', 'blue', ...]);

// Then In the loop through each leaves:
treeLayout.leaves().map((leaf) => {
  const parentName = leaf.parent?.data.name;
  const color = colorScale(parentName)

  // ... render rect using this color
}
Mark90Robert12Emily34Marion53Nicolas98Malki22Djé12Mélanie45Einstein76

Treemap with 2 levels of hierarchy and a color scale, made with react and d3.js.

Hover effect

Adding a hover effect to your treemap is a nice polish detail. Here I suggest to highlight the slice that is hovered over by dimming all the other slices.

There are several strategies available to implement such an effect. One can rely on css pseudo classes only, or add a css class using javascript and the onMouseEnter event. It's also possible to rely on an animation library like react-spring.

I'm preparing a full section on the topic. You can subscribe to my dataviz-universe newsletter to know when it will be ready. Meanwhile, there is a code sandbox waiting for you below to reveal the code of this example.

Subscribe
Mark90Robert12Emily34Marion53Nicolas98Malki22Djé12Mélanie45Einstein76

Hover over a group on the treemap to see the other groups fading.




Part Of A Whole

Contact

👋 Hey, I'm Yan and I'm currently working on this project!

Feedback is welcome ❤️. You can fill an issue on Github, drop me a message on Twitter, or even send me an email pasting yan.holtz.data with gmail.com. You can also subscribe to the newsletter to know when I publish more content!