Published
Edited
Apr 25, 2020
12 forks
Importers
16 stars
Insert cell
Insert cell
chart = {
const svg = d3.select(DOM.svg(width, height));
const boxWidth = 50;
const jitterWidth = 50;
const groups = svg.selectAll("g")
.data(data)
.join("g")
.attr("transform", d => `translate(${x(d.key)}, 0)`)
.attr("class", d => d.key);
groups
.selectAll("vertLine")
.data(d => [d.value.range])
.join("line")
.attr("class", "vertLine")
.attr("stroke", "#C0C0C0")
.attr('stroke-width','1px')
.style("width", 40)
.attr("x1", 0)
.attr("x2", 0)
.attr("y1", range => y(range[0]))
.attr("y2", range => y(range[1]));
groups
.selectAll("points")
.data(d => d.value)
.join("circle")
.attr("cx", d => 0 - jitterWidth/2 + Math.random() * jitterWidth)
.attr("cy", d => y(d.value))
.attr("r", 2)
.style("fill", "#af5f68")
.attr("fill-opacity", 0.8);
groups
.selectAll("box")
.data(d => [d])
.join("rect")
.attr("class", "box")
.attr("x", -boxWidth/2)
.attr("y", d => y(d.value.quartiles[2]))
.attr("height", d => y(d.value.quartiles[0])-y(d.value.quartiles[2]))
.attr("width", boxWidth)
.attr("stroke", "#808080")
.style("fill", "rgb(255, 255, 255)")
.style("fill-opacity", 0.7);
groups
.selectAll("horizontalLine")
.data(d => [d.value.range[0], d.value.quartiles[1], d.value.range[1]])
.join("line")
.attr("class", "horizontalLine")
.attr("stroke", "#808080")
.attr('stroke-width','1px')
.style("width", 40)
.attr("x1", -boxWidth/2)
.attr("x2", +boxWidth/2)
.attr("y1", d => y(d))
.attr("y2", d => y(d));

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

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

return svg.node();
}
Insert cell
Insert cell
data = d3.nest()
.key(function(d){ return d.name;})
.rollup(function (series) {
const bin = series.map(d => d);
const values = series.map(d => d.value);
values.sort((a, b) => a - b);
const min = values[0];
const max = values[values.length - 1];
const q1 = d3.quantile(values, 0.25);
const q2 = d3.quantile(values, 0.50);
const q3 = d3.quantile(values, 0.75);
const iqr = q3 - q1; // interquartile range
const r0 = Math.max(min, q1 - iqr * 1.5);
const r1 = Math.min(max, q3 + iqr * 1.5);
bin.quartiles = [q1, q2, q3];
bin.range = [r0, r1];
bin.outliers = bin.filter(v => v.value < r0 || v.value > r1); // TODO
return bin;
})
.entries(flatData);
Insert cell
x = d3.scaleBand()
.range([margin.left, width - margin.right])
.domain(data.map(d => d.key))
.paddingInner(1)
.paddingOuter(.5)
Insert cell
y = d3.scaleLinear()
.domain([d3.min(flatData, d => d.value), d3.max(flatData, d => d.value)]).nice()
.range([height - margin.bottom, margin.top])
Insert cell
Insert cell
Insert cell
Insert cell
margin = ({top: 20, right: 20, bottom: 30, left: 40})
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