boxenPlot = {
const svg = d3.select(DOM.svg(width, height));
const g = svg.append("g")
.selectAll("g")
.data(bins)
.join("g");
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
`);
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)}
`);
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();
}