Your code was almost complete; the only things missing were that you needed to add a fake root node to your hierarchy, to specify the accessor for the children, and to fix the value for the leaf nodes, which had an extra layer of nesting that needed to be removed.
Leaf node value:
var nested_data = d3.nest()[...].rollup(function(leaves) { return { value: leaves.length }}).entries(data);
results in leaf nodes like so:
{ value: { value: 5 } }
remove the extra value:
from the rollup
call:
var nested_data = d3.nest()[...].rollup(function(leaves) { return leaves.length}).entries(data);
and now your leaf nodes look like so:
{ value: 5 }
Fake root node
Ensure all your nested data is collected in the same hierarchy by adding a fake root:
d3.hierarchy({ values: nested_data })
Child node accessor
Specify the accessor for the children as otherwise d3 will look for x.children
, and if it isn't there, will assume the node is a leaf:
d3.hierarchy({ value: nested_data }, function(d) { return d.values })
Result:
const margin = { top: 40, right: 10, bottom: 10, left: 10};var width = 960 - margin.left - margin.right;var height = 960 - margin.top - margin.bottom;var color = d3.scaleOrdinal().range(d3.schemeCategory20b);var treemap = d3.treemap() .size([width, height]) .padding(1) .round(true);var json_data = d3.json("https://raw.githubusercontent.com/vega/vega/master/docs/data/cars.json", function(error, data) { if (error) throw error; var nested_data = d3.nest() .key(function(d) { return d.Origin; }) .key(function(d) { return d.Cylinders; }) .key(function(d) { return d.Miles_per_Gallon; }) .rollup(function(leaves) { return leaves.length }) .entries(data); var root = d3.hierarchy({ values: nested_data }, d => d.values) .sum(function(d) { return d.value; }) treemap(root); var nodes = d3.select('svg g') .selectAll('g') .data(root.descendants()) .enter() .append('g') .attr('transform', function(d) { return 'translate('+ [d.x0, d.y0] +')' }) nodes .append('rect') .attr('width', function(d) { return (d.x1 - d.x0) * 10; }) .attr('height', function(d) { return (d.y1 - d.y0) * 10; }) .attr('fill', function(d) { return color(d.data.key); }) nodes .append('text') .text(function(d) { return d.data.key; })});
body { font: 10px sans-serif; position: relative;}.node { box-sizing: border-box; line-height: 1em; overflow: hidden; position: absolute; white-space: pre; background: #ddd;}.node-label,.node-value { margin: 4px;}.node-value { margin-top: -2px;}.node-value { font-weight: bold;}
<title>My treemap</title><script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.2.2/d3.min.js"></script><svg width="1000" height="1000"><g></g></svg>