Skip to content

Commit

Permalink
feat(core): sampleWithReplacement
Browse files Browse the repository at this point in the history
Implements simple sampling with replacement, which, in contrast to the existing sample method,

allows an item to be chosen more than once.

Fixes #173
  • Loading branch information
tmcw committed Feb 17, 2017
1 parent 332ada9 commit 5436fde
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 0 deletions.
1 change: 1 addition & 0 deletions index.js
Expand Up @@ -26,6 +26,7 @@ ss.quantileSorted = require('./src/quantile_sorted');
ss.iqr = ss.interquartileRange = require('./src/interquartile_range');
ss.medianAbsoluteDeviation = ss.mad = require('./src/median_absolute_deviation');
ss.chunk = require('./src/chunk');
ss.sampleWithReplacement = require('./src/sample_with_replacement');
ss.shuffle = require('./src/shuffle');
ss.shuffleInPlace = require('./src/shuffle_in_place');
ss.sample = require('./src/sample');
Expand Down
41 changes: 41 additions & 0 deletions src/sample_with_replacement.js
@@ -0,0 +1,41 @@
'use strict';
/* @flow */

/**
* Sampling with replacement is a type of sampling that allows the same
* item to be picked out of a population more than once.
*
* @param {Array} population an array of any kind of element
* @param {number} n count of how many elements to take
* @param {Function} [randomSource=Math.random] an optional entropy source
* @return {Array} n sampled items from the population
* @example
* var sample = sampleWithReplacement([1, 2, 3, 4], 2);
* sampleWithReplacement; // = [2, 4] or any other random sample of 2 items
*/
function sampleWithReplacement/*::<T>*/(population/*:Array<T>*/,
n /*: number */,
randomSource/*:Function*/) {

if (population.length === 0) {
return [];
}

// a custom random number source can be provided if you want to use
// a fixed seed or another random number generator, like
// [random-js](https://www.npmjs.org/package/random-js)
randomSource = randomSource || Math.random;

var length = population.length;
var sample = [];

for (var i = 0; i < n; i++) {
var index = Math.floor(randomSource() * length);

sample.push(population[index]);
}

return sample;
}

module.exports = sampleWithReplacement;
19 changes: 19 additions & 0 deletions test/sample_with_replacement.test.js
@@ -0,0 +1,19 @@
/* eslint no-shadow: 0 */
'use strict';

var test = require('tap').test;
var Random = require('random-js');
var random = new Random(Random.engines.mt19937().seed(0));
var ss = require('../');

function rng() { return random.real(0, 1); }

test('sampleWithReplacement', function(t) {
var input = [1, 2, 3, 4, 5, 6];
t.deepEqual(ss.sampleWithReplacement(input, 2, rng), [6, 5]);
t.deepEqual(ss.sampleWithReplacement(input, 3, rng), [3, 6, 4]);
t.deepEqual(ss.sampleWithReplacement(input, 4, rng), [5, 2, 3, 4]);
t.deepEqual(ss.sampleWithReplacement(input, 0, rng), []);
t.deepEqual(ss.sampleWithReplacement([], 1, rng), []);
t.end();
});

0 comments on commit 5436fde

Please sign in to comment.