Skip to content

Instantly share code, notes, and snippets.

@ramhiser
Last active August 29, 2015 14:26
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ramhiser/692c52644db04d1afcc4 to your computer and use it in GitHub Desktop.
Save ramhiser/692c52644db04d1afcc4 to your computer and use it in GitHub Desktop.
Weighted random sample from a vector in JavaScript
// Weighted random sample from a vector
//
// By default, the `weights` are set to 1. This equates to equal weighting.
// Loosely based on http://codereview.stackexchange.com/a/4265
//
// If any weight is `null`, revert to default weights (i.e., all 1).
//
// A random-number generator (RNG) seed is optionally set via seedrandom.js.
// NOTE: The JS file is loaded via jQuery.
// Details: https://github.com/davidbau/seedrandom
//
// @param vector to sample
// @param weights optional array of weights
// @param seed optional RNG seed to reproduce
// @return random selection from `vector`
var sample = function(vector, weights, seed) {
weights_undefined = typeof weights === 'undefined';
has_null_weights = false;
if (!weights_undefined) {
has_null_weights = weights.some(function(x) {return x === null;})
}
if (weights_undefined || has_null_weights) {
weights = Array(vector.length);
for (i = 0; i < weights.length; i++) {
weights[i] = 1;
}
}
// Normalize weights to sum to 1
// For vector sum, source: http://stackoverflow.com/a/3762623/234233
weights_sum = weights.reduce(function(x, y) { return x + y; }, 0);
for (i = 0; i < weights.length; i++) {
weights[i] = weights[i] / weights_sum;
}
// Set RNG seed (if given)
var random_draw = null;
if (!(typeof seed === 'undefined')) {
$.getScript('http://cdnjs.cloudflare.com/ajax/libs/seedrandom/2.4.0/seedrandom.min.js')
.done(function() {
console.log('seedrandom.js loaded properly with seed: ' + seed);
Math.seedrandom(seed);
random_draw = Math.random();
}).fail(function() {
console.log('seedrandom.js failed to load');
});
}
if (!random_draw) {
random_draw = Math.random();
}
var cum_weights = 0;
for (i = 0; i < vector.length; i++) {
cum_weights += weights[i];
if (random_draw < cum_weights) {
return(vector[i]);
}
}
}
@ramhiser
Copy link
Author

ramhiser commented Aug 3, 2015

The RNG seed is set via seedrandom.js. NOTE: This file is loaded using jQuery's $.getScript.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment