Public
Edited
Apr 12, 2023
Insert cell
Insert cell
Insert cell
explore_tree = treeMapGenerator()
Insert cell
color_Scale = d3.scaleOrdinal(d3.schemeSet3)
Insert cell
height = 700
Insert cell
hierarchy = {
const dataCopy = JSON.parse(JSON.stringify(state_age_suicide_data));

return d3
.hierarchy(dataCopy)
.sum((d) => d.value)
.sort((a, b) => b.value - a.value);
}
Insert cell
treemap = d3
.treemap()
// set the size of the treemap render area
.size([width, height])
// set the padding between every rectangle in px
.padding(2)
// set the padding at the top of each group of rectangles
// so that we can fit the country labels
.paddingTop(10)
// Set the generator to round pixel values to the nearest value
// (makes things look better)
.round(true)
Insert cell
root = treemap(hierarchy)
Insert cell
function mapToTreeFormat(map) {
let arr = [];

for (let [key, val] of map.entries()) {
let obj = {};

obj = {
name: key
};

let child = [];
let obj2 = {};

for (let [k, v] of val.entries()) {
obj2 = {
name: k.split(" ")[0],
value: v
};

child.push(obj2);
}

obj = {
...obj,
children: child
};

arr.push(obj);
}

return arr;
}
Insert cell
sdata = FileAttachment("usa_suicides_2016_onwards.csv").csv()
Insert cell
mapped_data = d3.rollup(
sdata,
(v) =>
d3.mean(
v,
(d) =>
(parseInt(d.Count) * 100000) / parseInt(d.Population.replace(",", ""))
),
(d) => d.Race, // State.replace(/ *\([^)]*\) */g, "")
(d) => d[suicide_group]
// (d) => d["Age Groups"]
// (d) => d["Method"]
)
Insert cell
suicide_group
Insert cell
mapped_data.delete("")
Insert cell
state_age_suicide_data = ({
children: mapToTreeFormat(mapped_data)
})
Insert cell
function treeMapGenerator() {
const svg = d3
.create("svg")
.style("font-family", "sans-serif")
// .attr("width", 1400)
// .attr("height", 1100);
.attr("viewBox", [-20, -20, width, 800]); // w: + 20 * 2, h: + 20 * 2

const g = svg.append("g").attr("class", "treemap-container");

// Place the labels for our countries
g.selectAll("text.country")
// The data is the first "generation" of children
.data(root.children)
.join("text")
.attr("class", "country")
// The rest is just placement/styling
.attr("x", (d) => d.x0)
.attr("y", (d) => d.y0)
.attr("dy", "0.6em")
.attr("dx", 3)
.style("font-size", 12)
// Remember, the data on the original node is available on node.data (d.data here)
.text((d) => d.data.name);

// Now, we place the groups for all of the leaf nodes
const leaf = g
.selectAll("g.leaf")
// root.leaves() returns all of the leaf nodes
.data(root.leaves())
.join("g")
.attr("class", "leaf")
// position each group at the top left corner of the rect
.attr("transform", (d) => `translate(${d.x0},${d.y0})`)
.style("font-size", 10);

// A title element tells the browser to display its text value
// in a popover when the cursor is held over a rect. This is a simple
// way to add some interactivity
leaf
.append("title")
.text(
(d) =>
`${d.parent.data.name}-${d.data.name}\n${
d.value.toLocaleString() + " cases"
}`
);

// Now we append the rects. Nothing crazy here
leaf
.append("rect")
.attr("fill", (d) => color_Scale(d.parent.data.name))
.attr("opacity", 0.7)
// the width is the right edge position - the left edge position
.attr("width", (d) => d.x1 - d.x0)
// same for height, but bottom - top
.attr("height", (d) => d.y1 - d.y0)
// make corners rounded
.attr("rx", 3)
.attr("ry", 3);

// This next section checks the width and height of each rectangle
// If it's big enough, it places labels. If not, it doesn't.
leaf.each((d, i, arr) => {
// The current leaf element
const current = arr[i];

const left = d.x0,
right = d.x1,
// calculate its width from the data
width = right - left,
top = d.y0,
bottom = d.y1,
// calculate its height from the data
height = d.y1 - d.y0;

// too small to show text
const tooSmall = width < 34 || height < 25;

// and append the text (you saw something similar with the pie chart (day 6)
const text = d3
.select(current)
.append("text")
// If it's too small, don't show the text
.attr("opacity", tooSmall ? 0 : 0.9)
.selectAll("tspan")
.data((d) => [d.data.name, d.value.toLocaleString()])
.join("tspan")
.attr("x", 3)
.attr("y", (d, i) => (i ? "2.5em" : "1.15em"))
.text((d) => d);
});

return svg.node();
}
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more