Published unlisted
Edited
Dec 7, 2020
Importers
Insert cell
Insert cell
Insert cell
viewof d = distribution(6)
Insert cell
d
Insert cell
d.reduce((a, b) => a + b)
Insert cell
d3.range(6).map(x => 1 / 6)
Insert cell
function distribution(
n = 10,
d = d3.range(n).map(x => 1 / n),
height = 100,
width = 600
) {
const value = d;

const x = d3
.scaleLinear()
.domain([0, n])
.range([0, width]);

const y = d3
.scaleLog()
.domain([0.00001, 1])
.range([height, 0])
.clamp(true);

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

svg
.append("line")
.attr("x1", x(0))
.attr("x2", x(n))
.attr("y1", y(0))
.attr("y2", y(0))
.attr("stroke", "#000");

const rect = svg
.selectAll("rect")
.data({ length: n })
.join("rect")
.attr("x", (_, i) => x(i))
.attr("width", width / n - 2)
.attr("fill", "brown");

function update(frozen_index) {
normalize(frozen_index, value);
rect.attr("y", (_, i) => y(value[i]));
rect.attr("height", (_, i) => Math.abs(-y(value[i]) + y(0)));
svg.node().dispatchEvent(new CustomEvent('input'));
}

update(0);

const drag = d3
.drag()
.subject(event => Math.floor(x.invert(event.x)))
.on("drag", event => {
value[event.subject] = y.invert(event.y);
update(event.subject);
});

svg.call(drag);

return Object.assign(svg.node(), { value });

function normalize(frozen_index, D) {
const compsum = 1 - D.slice(0, frozen_index + 1).reduce((a, b) => a + b);
if (compsum >= 0) {
const parsum = D.slice(frozen_index + 1).reduce((a, b) => a + b);
const sum1 = parsum ? (1 * compsum) / parsum : 1;
for (let i = frozen_index; i < D.length; i++) D[i] *= sum1;
} else {
const max_partial = partialSums(D);
for (let i = max_partial; i < D.length; i++) D[i] = 0;
const parsum = D.slice(max_partial, frozen_index + 1).reduce(
(a, b) => a + b
);
const sum1 = parsum ? 1 / parsum : 1;
for (let i = max_partial + 1; i < D.length; i++)
D[i] = (D[i] + epsilon) * sum1;
}
return D;
}
}
Insert cell
1 + epsilon
Insert cell
epsilon = 10 ** -15
Insert cell
function partialSums(iterable) {
let s = 0;
let max_partial = 0;
for (const [i, x] of iterable.entries()) {
if (s<1){
s += x;
max_partial = i;
}
}
return max_partial
}
Insert cell
import {slider, color, input} from '@jashkenas/inputs'
Insert cell
d3 = require("d3@6")
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