Published
Edited
May 15, 2020
4 stars
Insert cell
Insert cell
Insert cell
boxenPlot = {
const svg = d3.select(DOM.svg(width, height));

const g = svg.append("g")
.selectAll("g")
.data(bins)
.join("g");
// boxes
g.selectAll(".box")
.data(d => d.quantiles.map((e, i) => {
const width = x(d.x1) - x(d.x0),
elemWidth = width / Math.pow(1.5, d.depth - i - 1),
offset = (width - elemWidth) / 2;
return {
x0: d.x0,
x1: d.x1,
offset: offset,
depth: d.depth,
lower: e[0],
upper: e[1]
};
}))
.join("path")
.attr("class", "box")
.style("fill", (d, i) => blues[d.depth - i])
.attr("d", (d, i) => `
M${x(d.x0) + 1 + d.offset}, ${y(d.upper)}
H${x(d.x1) - d.offset}
V${y(d.lower)}
H${x(d.x0) + 1 + d.offset}
Z
`);
// median
g.append("path")
.attr("stroke", "currentColor")
.attr("stroke-width", 2)
.attr("d", d => `
M${x(d.x0) + 1},${y(d.median)}
H${x(d.x1)}
`);
// outliers
g.append("g")
.attr("fill", "steelblue")
.attr("fill-opacity", 0.2)
.attr("stroke", "none")
.attr("transform", d => `translate(${x((d.x0 + d.x1) / 2)},0)`)
.selectAll("circle")
.data(d => d.outliers)
.join("circle")
.attr("r", 2)
.attr("cx", () => (Math.random() - 0.5) * 4)
.attr("cy", d => y(d.y));

svg.append("g")
.call(xAxis);

svg.append("g")
.call(yAxis);

return svg.node();
}
Insert cell
blues = d3.schemeBlues[9].reverse()
Insert cell
bins.map(bin => bin.depth)
Insert cell
bins = d3.histogram()
.thresholds(width / 40)
.value(d => d.x)
(data)
.map(bin => {
bin.sort((a, b) => a.y - b.y);
const values = bin.map(d => d.y);
const n = values.length;
// number of boxes
let depth = Math.floor(Math.log2(n) - 3);
if (!depth || depth < 1) {
depth = 1;
}
const upper = d3.range(depth).reverse().map(d => 1 - Math.pow(0.5, d + 2));
const lower = d3.range(depth).reverse().map(d => Math.pow(0.5, d + 2));
const quantileEnds = d3.zip(lower, upper);
const quantiles = quantileEnds.map(ends => ends.map(e => d3.quantile(values, e)));
const edges = quantiles[0];
const outliers = bin.filter(v => v.y < edges[0] || v.y > edges[1]);
bin.median = d3.quantile(values, 0.5);
bin.depth = depth;
bin.quantiles = quantiles;
bin.outliers = outliers;
return bin;
})
Insert cell
boxPlot
Insert cell
height = 600
Insert cell
import {data, x, y, xAxis, yAxis, chart as boxPlot} from "@d3/box-plot"
Insert cell
d3 = require("d3@5")
Insert cell
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