Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sampling a random subset from an array

What is a clean way of taking a random sample, without replacement from an array in javascript? So suppose there is an array

x = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15] 

and I want to randomly sample 5 unique values; i.e. generate a random subset of length 5. To generate one random sample one could do something like:

x[Math.floor(Math.random()*x.length)]; 

But if this is done multiple times, there is a risk of a grabbing the same entry multiple times.

like image 679
Jeroen Ooms Avatar asked Aug 13 '12 13:08

Jeroen Ooms


People also ask

How do you randomly sample a matrix?

To take a random sample from a matrix in R, we can simply use sample function and if the sample size is larger than the number of elements in the matrix replace=TRUE argument will be used.

How do you select a random sample from a list in Python?

In Python, you can randomly sample elements from a list with choice() , sample() , and choices() of the random module. These functions can also be applied to a string and tuple. choice() returns one random element, and sample() and choices() return a list of multiple random elements.


2 Answers

I suggest shuffling a copy of the array using the Fisher-Yates shuffle and taking a slice:

function getRandomSubarray(arr, size) {     var shuffled = arr.slice(0), i = arr.length, temp, index;     while (i--) {         index = Math.floor((i + 1) * Math.random());         temp = shuffled[index];         shuffled[index] = shuffled[i];         shuffled[i] = temp;     }     return shuffled.slice(0, size); }  var x = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]; var fiveRandomMembers = getRandomSubarray(x, 5); 

Note that this will not be the most efficient method for getting a small random subset of a large array because it shuffles the whole array unnecessarily. For better performance you could do a partial shuffle instead:

function getRandomSubarray(arr, size) {     var shuffled = arr.slice(0), i = arr.length, min = i - size, temp, index;     while (i-- > min) {         index = Math.floor((i + 1) * Math.random());         temp = shuffled[index];         shuffled[index] = shuffled[i];         shuffled[i] = temp;     }     return shuffled.slice(min); } 
like image 162
Tim Down Avatar answered Oct 01 '22 11:10

Tim Down


A little late to the party but this could be solved with underscore's new sample method (underscore 1.5.2 - Sept 2013):

var x = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15];  var randomFiveNumbers = _.sample(x, 5); 
like image 25
alengel Avatar answered Oct 01 '22 10:10

alengel