Public
Edited
Jul 1, 2024
27 stars
Insert cell
Insert cell
cents = d3.ticks(0, 10, 1000)
Insert cell
index = d3.bisect(cents, Math.PI)
Insert cell
[cents[index - 1], cents[index]]
Insert cell
Insert cell
Insert cell
Insert cell
sorted = {
replay;
const sorted = [];
do {
const x = Math.random();
const i = d3.bisect(sorted, x);
sorted.splice(i, 0, x); // insert "x" at rank i, deleting 0 element
yield sorted;
} while (sorted.length < 225);
}
Insert cell
Insert cell
d3.bisect([0, 1, 1, 2], 1)
Insert cell
d3.bisectRight([0, 1, 1, 2], 1)
Insert cell
d3.bisectLeft([0, 1, 1, 2], 1)
Insert cell
Insert cell
numbers = Array.from({length: 1000}, (_, i) => Math.floor(Math.sqrt(i)))
Insert cell
n = 20
Insert cell
pos = [d3.bisectLeft(numbers, n), d3.bisectRight(numbers, n)]
Insert cell
Insert cell
Insert cell
// A synthetic dataset
// to load your own, use data = d3.json(url)
// or data = require("@observablehq/aapl")
data = Array.from(
(function*() {
let date = new Date("2007-04-24"),
close = 98.84;
for (let i = 0; i < 1280; i++) {
if (i % 7 > 5) continue; // ignore 2 days per week
date = new Date(date.setDate(date.getDate() + 1));
close = +(close + Math.random() - 0.485).toFixed(2);
yield { date, close };
}
})()
)
Insert cell
Insert cell
bisect = d3.bisector(d => d.date)
Insert cell
bisect.right(data, new Date(2010, 0, 9))
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
{
const height = 250;

const chart = d3
.create("svg")
.attr("width", width)
.attr("height", height);

yield chart.node();

const y = d3
.scaleLinear()
.domain([0, 12])
.range([10, height - 10]),
extent = d3.extent(data, d => d.date),
x = d3
.scaleLinear()
.domain(extent)
.range([10, width - 10]);

function X(pos) {
return x(pos < data.length ? data[pos].date : extent[1]);
}

const last = positions.length - 1,
l = positions[last];

chart
.append("line")
.attr("y2", height)
.attr("style", "stroke:#999; stroke-width:0.5; stroke-dasharray: 5 3;")
.attr("x1", X(l))
.attr("x2", X(l));

chart
.append("g")
.selectAll("line")
.data(d3.pairs(positions))
.join("line")
.attr("x1", d => X(d[0]))
.attr("x2", d => X(d[1]))
.attr("y1", (_, i) => y(i))
.attr("y2", (_, i) => y(i + 1))
.style("stroke", "#ccc");

chart
.append("g")
.selectAll("circle")
.data(positions.slice(0, -1))
.join("circle")
.attr("r", 2)
.attr("cx", d => X(d))
.attr("cy", (_, i) => y(i));

chart
.append("circle")
.attr("r", 3)
.attr("cx", X(l))
.attr("cy", y(last))
.style("fill", "red");

chart.on("pointermove click", function(event) {
const m = d3.pointer(event, this);
const date = x.invert(m[0]);
const i = bisect.right(data, date);
mutable lookup = new Date(date);
});
}
Insert cell
positions = [...bisectSteps(data, lookup, d => d.date)]
Insert cell
Insert cell
Insert cell
{
const sorted = [];
const bisector = d3.bisector(d3.descending).right;
do {
const x = ((Math.random() * 1000) | 0) / 1000;
const i = bisector(sorted, x);
sorted.splice(i, 0, x); // inserts "x" at rank i, deleting 0 element
yield sorted;
} while (sorted.length < 255);
}
Insert cell
Insert cell
Insert cell
d3.bisect(cents, 4, 500, 700) // try different bounds!
Insert cell
d3.bisect(cents, 6, 500, 700)
Insert cell
d3.bisect(cents, 8, 500, 700)
Insert cell
Insert cell
Insert cell
function* bisectSteps(a, x, accessor = d => d) {
let lo = 0,
hi = a.length;
while (lo < hi) {
var mid = (lo + hi) >>> 1;
yield mid;
if (d3.ascending(accessor(a[mid]), x) < 0) lo = mid + 1;
else hi = mid;
}
yield lo;
}
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