Published
Edited
May 28, 2020
11 stars
Also listed in…
Clustering
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
r = regressionGenerator(data)
Insert cell
function difference(data, k = 1) {
const sob = [];
for (let i = 0; i < data.length; i++) {
const j = i < k ? k : i + k >= data.length ? data.length - 1 - k : i;
sob[i] = 0;
for (let u = 1; u <= k; u++)
sob[i] += (data[j + u][1] - data[j - u][1]) / k;
}
return sob;
}
Insert cell
diffs = {
const s = difference(r),
m = compare_to.match(/median/) ? d3.median(s) : 0; // median is more robust to outliers than mean
return s.map(d => d - m || 1e-12) /* enforce +sign for the median */;
}
Insert cell
plateaus = {
let i = 0;
const t = [],
stddev = d3.deviation(diffs),
zeros = diffs.map(d => (Math.abs(d) < plateau_tolerance * stddev ? 1 : -1));
for (const [a, b] of d3.pairs(zeros)) {
if (a * b < 0 || i == 0 || i == diffs.length - 2)
t.push([r[i][0], Math.sign(b)]);
i++;
}
return t;
}
Insert cell
regimes = {
const t = [];
let i = 0;
for (const [a, b] of d3.pairs(diffs)) {
if (a * b < 0 || i == 0 || i == diffs.length - 2)
t.push([r[i][0], Math.sign(b)]);
i++;
}
return t;
}
Insert cell
// filter out small slivers
thresholds = {
const t = (show_plateaus ? plateaus : regimes).slice();
for (let i = 1; i < t.length - 1; i++) {
if (t[i + 1][0] - t[i][0] < 4) {
t[i] = t[i + 1] = null;
i++;
}
}
return t.filter(d => d);
}
Insert cell
data = {
switch (dataSource) {
case "squared":
return d3.range(1901, 2020, 1).map(year => ({
year,
value: ((year - 1930) / 10) ** 2
}));
case "sinusoid":
return d3.range(1901, 2020, 0.2).map(year => ({
year,
value: 10 + 5 * Math.sin(year / 5)
}));
case "log":
return d3.range(1901, 2020, 2).map(year => ({
year,
value: 2 * Math.log(year - 1900) + .5 * Math.random()
}));
case "staircase":
return d3.range(1901, 2020, 3).map(year => ({
year,
value: (year / 30) | 0
}));
case "combined":
return d3.range(1901, 2020, 0.2).map(year => ({
year,
value: year / 5 + 5 * Math.sin(year / 5) + Math.random()
}));
default:
return data0;
}
}
Insert cell
Insert cell
Insert cell
regressionGenerator = d3.regressionLoess()
.x(d => d.year)
.y(d => d.value)
.bandwidth(bandwidth);
Insert cell
Insert cell
lineGenerator = d3.line()
.x(d => xScale(d[0]))
.y(d => yScale(d[1]));
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
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