choices = [a,a,a,a,b,b,c]
random.choice(choices)
As you can see a is most likely to be chosen but is there a better/shorter way of doing this?
choices = [a,a,a,a,b,b,c]
random.choice(choices)
As you can see a is most likely to be chosen but is there a better/shorter way of doing this?
If you use choices
, not choice
, you can specify a weight for each element.
random.choices([a,b,c], [4,2,1])
The second argument are the relative weights for each element in the first argument. For example, in the following you can see that a
was chosen roughly twice as often as b
and roughly four times as often as c
.
>>> import collections, random
>>> collections.Counter(random.choices('abc', [4,2,1], k=100))
Counter({'a': 58, 'b': 25, 'c': 17})
If you are not using Python 3.6+ (support for weights in random.choices
), you can construct a population:
import random
a, b, c = 'abc'
weighted = [(a, 4), (b, 2), (c, 1)]
population = [x for x, weight in weighted for _ in range(weight)]
random.choice(population)
If you are worried about performance for large weight values, you can use itertools.accumulate
and bisect
:
import bisect
import itertools
import random
choices = ['a', 'b', 'c']
weights = [4, 2, 1]
cumulative_weights = list(itertools.accumulate(weights))
print(choices[bisect.bisect(cumulative_weights, random.random() * cumulative_weights[-1])])