Published
Edited
Jul 12, 2020
2 forks
Importers
15 stars
Insert cell
Insert cell
Insert cell
function gen_expon(lambda){
return -Math.log(1-Math.random())/lambda;
}
Insert cell
gen_expon(15)
Insert cell
Insert cell
function gen_pois(lambda, max_its = 1000){
let i = -1, cum_sum = 0;
while(cum_sum < 1 && i < max_its){
i++;
cum_sum += -Math.log(1-Math.random())/lambda; // Or use gen_expon()
}
return i;
}
Insert cell
gen_pois(15)
Insert cell
Insert cell
function gen_discrete_unif(min = 0, max = 100){
const range = max - min;
return Math.round(Math.random()*range) + min;
}
Insert cell
gen_discrete_unif(0, 20)
Insert cell
Insert cell
Insert cell
function copy_array(arr){
return arr.map(obj => Object.assign({}, obj));
}
Insert cell
copy_array([{a: 1, b: 2}, {a: 2, b: 5}])
Insert cell
Insert cell
seq = function({ range, n, step, pad = 0 }) {
const [from, to] = range;
const width = to - from - 2 * pad;
let step_size, length;

if (n) {
length = n;
step_size = width / (length - 1);
} else {
step_size = step;
length = Math.ceil(width / step_size) + 1;
}

return Float32Array.from({ length }).map(
(_, i) => from + pad + step_size * i
);
}
Insert cell
seq({ range: [0, 2], n: 5, pad: 0.1 })
Insert cell
seq({ range: [0, 2], step: 0.2 })
Insert cell
Insert cell
function weighted_sample(weights, values){
const random_val = Math.random();
let cumulative_prob = 0, i;
for(i = 0; i < weights.length; i++){
cumulative_prob += weights[i];
if(cumulative_prob > random_val) break;
}
// If we have values, return which one, otherwise just return index
return values ? values[i]: i;
}
Insert cell
weighted_sample([0.1, 0.6, 0.3], ['a', 'b', 'c']);
Insert cell
weighted_sample([0.1, 0.6, 0.3]);
Insert cell
Insert cell
function weighted_samples({ vec, weight_id = null, n }) {
// Leaving weight_id as empty will do an unweighted sample
let total_weight = 0;
let to_sample = [];

vec.forEach((d, i) => {
const w = weight_id ? d[weight_id] : 1;
if (w > 0) {
// Only try sampling values with non-zero weights
total_weight += w;
to_sample.push({ w, i });
}
});

const sampled = [];

for (let k = 0; k < n; k++) {
const end_weight = Math.random() * total_weight;

let cumulative_weight = 0;
for (let j = 0; j < to_sample.length; j++) {
const { w, i } = to_sample[j];
cumulative_weight += w;
if (cumulative_weight >= end_weight) {
total_weight -= w;
sampled.push(to_sample.splice(j, 1)[0]);
break;
}
// sanity check to make sure we've got a value to go with.
if (total_weight === 0 || to_sample.length === 0) break;
}
}

return sampled.map(d => vec[d.i]);
}
Insert cell
weighted_samples({
vec: [
{ id: "a", w: 5 },
{ id: "b", w: 4 },
{ id: "c", w: 3 },
{ id: "d", w: 2 }
],
weight_id: "w",
n: 3
})
Insert cell
{
const n_sims = 50000;
const n_samples = 10;
const n_els = 40;

const data = Array.from({ length: n_els }).map((_, i) => ({
id: i,
w: 1 / (i + 1)
}));

const times_sampled = {};

data.forEach(d => (times_sampled[d.id] = 0));

for (let i = 0; i < n_sims; i++) {
const samples = weighted_samples({
vec: data,
weight_id: "w",
n: n_samples
});

samples.forEach(({ id }) => {
times_sampled[id]++;
});
}

const total_samples = n_sims * n_samples;
const props_sampled = [];
Object.keys(times_sampled).forEach(id =>
props_sampled.push({ id: +id, p: times_sampled[id] / total_samples })
);

return vegalite({
title: `Proportion of times sampled in ${n_samples} weighted draws over ${n_sims} simulations`,
width: width / 1.5,
data: { values: props_sampled },
mark: "bar",
encoding: {
x: {
field: "id",
title: "element",
type: "ordinal"
},
y: {
field: "p",
title: "prop sampled",
type: "quantitative"
}
}
});
}
Insert cell
Insert cell
function product(arr){
return arr.reduce((p, d) => p*d, 1);
}
Insert cell
product([1,2,3])
Insert cell
Insert cell
function sum(arr){
return arr.reduce((s, el) => s + el, 0);
}
Insert cell
sum([1,2,3,4])
Insert cell
Insert cell
function normalize(arr){
const total_size = arr.reduce((s, el) => s + el, 0);
// or sum(arr);
return arr.map(el => el/total_size);
}
Insert cell
normalize([1,2,3,4])
Insert cell
sum(normalize([2,3,4,6,7]))
Insert cell
Insert cell
function intersection(arr1, arr2){
return arr1.filter(n => arr2.includes(n));
}
Insert cell
intersection(
['a', 'b', 'c'],
['b', 'c', 'd']
)
Insert cell
Insert cell
function flatten(arr){
return [].concat(...arr);
}
Insert cell
flatten([
['a', 'b'],
['c', 'd'],
['e', 'f']
])
Insert cell
Insert cell
function unique(vec){
return [...new Set(vec)];
}
Insert cell
unique(['a', 'a', 'b', 'c', 'c', 'd'])
Insert cell
Insert cell
function init_array(n, fill = (_,i) => i){
return Array.from({length: n},
fill === null
? undefined
: typeof fill === 'function'
? fill
: () => fill);
}
Insert cell
init_array(4, (d,i) => i + 1).reverse()
Insert cell
// Defaults to filling with index
init_array(5);
Insert cell
// Can simply supply empty array
init_array(5, null);
Insert cell
// Fill with constant
init_array(5, 'a');
Insert cell
// Combine with probability functions
init_array(5, () => gen_pois(10));
Insert cell
Insert cell
Insert cell
all_equal = function(a, b) {
if (!b) return false;

const a_keys = Object.keys(a);
const b_keys = Object.keys(b);

// If number of keys differ then they cant be the same
if (a_keys.length !== b_keys.length) return false;

// If the union of the two keys is not the same length then they have different keys
const all_keys = new Set([...a_keys, ...b_keys]);
if (all_keys.size !== a_keys.length) return false;

// Now that we know all the keys are the same, test equality of values
for (let key in a) {
if (a[key] !== b[key]) return false;
}

return true;
}
Insert cell
all_equal({ a: 1, b: 2, c: 3 }, { a: 1, b: 2, c: 3 })
Insert cell
all_equal({ a: 1, b: 2, c: 4 }, { a: 1, b: 2, c: 3 })
Insert cell
all_equal({ a: 1, b: 2, c: 4 }, { a: 1, b: 2, c: 4, d: 5 })
Insert cell
vegalite = require("@observablehq/vega-lite@0.1")
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