How to randomly select an item from a list?
Assume I have the following list:
foo = ['a', 'b', 'c', 'd', 'e']
What is the simplest way to retrieve an item at random from this list?
If you want close to truly random, then I suggest secrets.choice
from the standard library [New in Python 3.6.]:
>>> from secrets import choice # Python 3 only
>>> choice[list['abcde']]
'c'
The above is equivalent to my former recommendation, using a SystemRandom
object from the random
module with the choice
method -
available earlier in Python 2:
>>> import random # Python 2 compatible
>>> sr = random.SystemRandom[]
>>> foo = list['abcde']
>>> foo
['a', 'b', 'c', 'd', 'e']
And now:
>>> sr.choice[foo]
'd'
>>> sr.choice[foo]
'e'
>>> sr.choice[foo]
'a'
>>> sr.choice[foo]
'b'
>>> sr.choice[foo]
'a'
>>> sr.choice[foo]
'c'
>>> sr.choice[foo]
'c'
If you want a deterministic pseudorandom selection, use the choice
function [which is actually a bound method on a Random
object]:
>>> random.choice
It seems random, but it's actually not, which we can see if we reseed it repeatedly:
>>> random.seed[42]; random.choice[foo], random.choice[foo], random.choice[foo]
['d', 'a', 'b']
>>> random.seed[42]; random.choice[foo], random.choice[foo], random.choice[foo]
['d', 'a', 'b']
>>> random.seed[42]; random.choice[foo], random.choice[foo], random.choice[foo]
['d', 'a', 'b']
>>> random.seed[42]; random.choice[foo], random.choice[foo], random.choice[foo]
['d', 'a', 'b']
>>> random.seed[42]; random.choice[foo], random.choice[foo], random.choice[foo]
['d', 'a', 'b']
A comment:
This is not about whether random.choice is truly random or not. If you fix the seed, you will get the reproducible results -- and that's what seed is designed for. You can pass a seed to SystemRandom, too.
sr = random.SystemRandom[42]
Well, yes you can pass it a "seed" argument, but you'll see that the SystemRandom
object simply ignores it:
def seed[self, *args, **kwds]:
"Stub method. Not used for a system random number generator."
return None
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. sample[]
is used for random sampling without replacement, and choices[]
is used for random sampling with replacement.
- random — Generate pseudo-random numbers — Python 3.8.1 documentation
This article describes the following contents.
- Pick a random element:
random.choice[]
- Random sample without replacement:
random.sample[]
- Random sample with replacement:
random.choices[]
- Initialize the random number generator:
random.seed[]
If you want to select elements from a list by conditions, see the following article.
- Extract, replace, convert elements of a list in Python
If you want to shuffle the entire list, or get a list of random numbers, see the following article.
- Shuffle a list, string, tuple in Python [random.shuffle, sample]
- Generate random int/float in Python [random, randrange, randint, etc.]
Pick a random element: random.choice[]
random.choice[]
returns a random element from a list.
- random.choice[] — Generate pseudo-random numbers — Python 3.8.1 documentation
import random
l = [0, 1, 2, 3, 4]
print[random.choice[l]]
# 1
Tuples and strings are processed similarly. In the case of a string, one character is returned.
print[random.choice[['xxx', 'yyy', 'zzz']]]
# yyy
print[random.choice['abcde']]
# b
An error is raised if a list, tuple, or string is empty.
# print[random.choice[[]]]
# IndexError: Cannot choose from an empty sequence
Random sample without replacement: random.sample[]
random.sample[]
randomly samples multiple elements from a list without replacement.
Pass a list to the first argument and the number of elements you want to get to the second argument. A list is returned.
- random.sample — Generate pseudo-random numbers — Python 3.8.1 documentation
import random
l = [0, 1, 2, 3, 4]
print[random.sample[l, 3]]
# [1, 3, 2]
print[type[random.sample[l, 3]]]
#
If the second argument is set to 1
, a list with one element is returned. If set to 0
, an empty list is returned. If set to the value that exceeds the number of elements of the list, an error is raised.
print[random.sample[l, 1]]
# [0]
print[random.sample[l, 0]]
# []
# print[random.sample[l, 10]]
# ValueError: Sample larger than population or is negative
Even if you pass a tuple or a string to the first argument, the list is returned.
print[random.sample[['xxx', 'yyy', 'zzz'], 2]]
# ['xxx', 'yyy']
print[random.sample['abcde', 2]]
# ['a', 'e']
To convert a list to a tuple or string, use tuple[]
, join[]
.
- Convert list and tuple to each other in Python
- Concatenate strings in Python [+ operator, join, etc.]
print[tuple[random.sample[['xxx', 'yyy', 'zzz'], 2]]]
# ['yyy', 'xxx']
print[''.join[random.sample['abcde', 2]]]
# de
Note that if the original list or tuple contains duplicate elements, the same value may be selected.
l_dup = [0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3]
print[random.sample[l_dup, 3]]
# [3, 1, 1]
If you want to avoid duplicate values, use set[]
to convert lists and tuples to set
, extract only unique elements, and then use sample[]
.
- Remove/extract duplicate elements from list in Python
print[set[l_dup]]
# {0, 1, 2, 3}
print[random.sample[set[l_dup], 3]]
# [1, 3, 2]
Random sample with replacement: random.choices[]
random.choices[]
randomly samples multiple elements from a list with replacement.
random.choices[]
was added in Python 3.6 and cannot be used in earlier versions.
- random.choices[] — Generate pseudo-random numbers — Python 3.8.1 documentation
Specify the number of elements you want to get with the argument k
. Since elements are chosen with replacement, k
can be larger than the number of
elements in the original list.
Since k
is a keyword-only argument, it is necessary to specify like k=3
.
import random
l = [0, 1, 2, 3, 4]
print[random.choices[l, k=3]]
# [2, 1, 0]
print[random.choices[l, k=10]]
# [3, 4, 1, 4, 4, 2, 0, 4, 2, 0]
k
is set to 1
by default. If omitted, a list with one element is returned.
print[random.choices[l]]
# [1]
You can specify the weight [probability] for each element to the weights
argument. The type of the list element specified in weights
can be either int
or float
. If set to 0
, the element is not selected.
print[random.choices[l, k=3, weights=[1, 1, 1, 10, 1]]]
# [0, 2, 3]
print[random.choices[l, k=3, weights=[1, 1, 0, 0, 0]]]
# [0, 1, 1]
Cumulative weights can be specified in the argument cum_weights
. cum_weights
in the following sample code is equivalent to the first weights
in the above code.
print[random.choices[l, k=3, cum_weights=[1, 2, 3, 13, 14]]]
# [3, 2, 3]
By default, both weights
and cum_weights
are set to None
, and each element is selected with the same probability.
If the length [number of elements] of weights
or cum_weights
is different from the original list, an error is raised.
# print[random.choices[l, k=3, weights=[1, 1, 1, 10, 1, 1, 1]]]
# ValueError: The number of weights does not match the population_
Also, an error is raised if you specify weights
and
cum_weights
at the same time.
# print[random.choices[l, k=3, weights=[1, 1, 1, 10, 1], cum_weights=[1, 2, 3, 13, 14]]]
# TypeError: Cannot specify both weights and cumulative weights
In the sample code so far, a list was specified to the first argument, but the same applies to a tuple and string.
Initialize the random number generator: random.seed[]
You can initialize a random number generator with random.seed[]
.
After initializing with the same seed, the element is selected in the same way.
random.seed[0]
print[random.choice[l]]
# 3
random.seed[0]
print[random.choice[l]]
# 3