Published
Edited
May 27, 2021
Insert cell
Insert cell
FileAttachment("processed.csv")
Insert cell
FileAttachment("processed.csv").text()
Insert cell
results = d3.csvParse(await FileAttachment("processed.csv").text(), d3.autoType)
Insert cell
d3.extent(results, d => d.logRT)
Insert cell
RTs = results.map(d => d.logRT)
Insert cell
import {chart as RThist} with {RTs as data, height} from "@d3/histogram"
Insert cell
RThist
Insert cell
md`# D3 way`
Insert cell
viewof sliderQuantile = slider({
min: 0,
max: 1,
step: 0.01,
format: ".0%",
description: "Quantile"
})
Insert cell
quartilesData = [sliderQuantile].map(x =>
d3.quantile(_.map(results, "logRT"), x)
)
Insert cell
d3Chart = {
const margin = { t: 20, r: 20, b: 20, l: 30 };

const xScale = d3
.scaleLinear()
.domain(d3.extent(results, d => d.logRT))
.range([margin.l, width - margin.r])
.nice();
const xAxis = g =>
g
.attr("transform", `translate(0, ${height - margin.b})`)
.call(
d3
.axisBottom(xScale)
.ticks(width / 80)
.tickSizeOuter(0)
)
.call(g =>
g
.selectAll(".tick text")
.attr("font-size", 11)
.attr("y", 12)
);

const hist = d3
.histogram()
.value(d => d.logRT)
.domain(xScale.domain())
.thresholds(xScale.ticks(width / 40));
const histData = hist(results);
const histPadding = 1;

const yScale = d3
.scaleLinear()
.domain([0, d3.max(_.map(histData, "length")) * 1.1])
.range([height - margin.b, margin.t]);
const yAxis = g =>
g
.attr("transform", `translate(${margin.l}, 0)`)
.call(
d3
.axisRight(yScale)
.ticks(height / 40)
.tickSizeOuter(0)
.tickSize(width - margin.l - margin.r)
)
.call(g => g.select(".domain").remove())
.call(g =>
g
.selectAll(".tick:not(:first-of-type) line")
.attr("stroke-opacity", 0.5)
.attr("stroke-dasharray", 3)
)
.call(g =>
g
.selectAll(".tick text")
.attr("x", 4)
.attr("dy", -4)
.attr("font-size", 12)
)
.call(g => g.select(".tick:first-of-type text").remove())
.call(g => g.select(".tick:last-of-type text").text(d => "n = " + d));

const svg = d3.create("svg").attr("viewBox", [0, 0, width, height]);

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

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

const rect = svg
.append("g")
.classed("bars", true)
.selectAll("rect")
.data(histData)
.join("rect")
.attr(
"transform",
d => `translate(${xScale(d.x0) + histPadding}, ${yScale(d.length)})`
)
.attr("width", d =>
d.length != 0
? xScale(d.x1) - xScale(d.x0) - histPadding * 2
: xScale(d.x1) - xScale(d.x0)
)
.attr("height", d => height - yScale(d.length) - margin.b)
.style("fill", "#69b3a2");

let quantileLines = svg
.append("g")
.classed("quartiles", true)
.selectAll("line");

const text = svg
.append("g")
.classed("labels", true)
.selectAll("text")
.data(histData)
.join("text")
.attr(
"transform",
d =>
`translate(${xScale(d.x0) +
(xScale(d.x1) - xScale(d.x0)) / 2}, ${yScale(d.length)})`
)
.attr("text-anchor", "middle")
.attr("y", -7)
.attr("font-family", "IBM Plex Mono")
.attr("font-size", 12)
.attr("fill", "black")
.attr("paint-order", "stroke")
.attr("stroke-width", 5)
.attr("stroke", "white")
.text(d => (d.length < 10 ? "" : d.length));

return Object.assign(svg.node(), {
update(inputQuartile) {
quantileLines = quantileLines
.data(inputQuartile)
.join("line")
.attr("y1", yScale.range()[0])
.attr("y2", yScale.range()[1])
.attr("x1", d => xScale(d))
.attr("x2", d => xScale(d))
.attr("stroke", "black")
.attr("stroke-width", 2)
.attr("stroke-dasharray", 5);
}
});
}
Insert cell
d3Chart.update(quartilesData)
Insert cell
height = 300
Insert cell
import {slider} from "@jashkenas/inputs"
Insert cell
d3 = require("d3@6")
Insert cell
_ = require("lodash")
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