Recipe 18.3. Generating Random Samples with Replacement
Credit: Sean Ross
Problem
You need to generate random samples with replacement out of a
"population" of items that are held
in a sequence.
Solution
A generator for the purpose is quintessentially simple:
import random
def sample_wr(population, _choose=random.choice):
while True: yield _choose(population)
Discussion
random.sample lets you do random sampling without
replacement, and Recipe 18.4, which follows, shows a
generator to perform sampling without replacement with excellent
memory-consumption characteristics. This recipe provides a generator
for sampling with replacement, which is an even
simpler task. Basically all the work gets delegated to
random.choice. The sample_wr
generator shown in this recipe is unbounded: used on its own, it will
keep looping forever. To bound the output of an intrinsically
unbounded generator, you can use it in a for
statement that at some point executes a break, or
use other techniques shown in Recipe 19.2.For example, to make a random string of 50 lowercase ASCII letters:
import itertoolsstring.ascii_lowercase is exactly the string
from string import ascii_lowercase
x = ''.join(itertools.slice(sample_wr(ascii_lowercase), 50))
'abcdefghijklmnopqrstuvwxyz'. If you
didn't have the sample_wr
generator, the equivalent code might be something like:
from string import ascii_lowercaseSo, the practical added-value of sample_wr is
from random import choice
x = ''.join([ random.choice(ascii_lowercase) for i in xrange(50) ])
modest, when compared to other available building-blocks. It is,
however, preferable to have such a fundamental concept of statistics
as sampling with replacement embodied as its own
function, rather than having to implement it with an explicit loop
over random.choice each time it is needed.
See Also
Library Reference and Python in a
Nutshell docs for module random.