Начиная с Python v3.6, random.choicesможет использоваться для возврата listэлементов заданного размера из заданной совокупности с необязательными весами.
random.choices(population, weights=None, *, cum_weights=None, k=1)
население : listсодержит уникальные наблюдения. (Если пусто, поднимает IndexError)
веса : точнее относительные веса, необходимые для выбора.
cum_weights : совокупные веса, необходимые для выбора.
k : размер ( len) объекта listдля вывода. (По умолчанию len()=1)
Несколько предостережений:
1) Используется взвешенная выборка с заменой, чтобы вытянутые элементы впоследствии были заменены. Значения в последовательности весов сами по себе не имеют значения, но их относительное соотношение имеет значение.
В отличие от того, np.random.choiceкоторый может принимать только вероятности в качестве весов, а также который должен обеспечивать суммирование индивидуальных вероятностей до 1 критерия, здесь нет таких правил. Пока они принадлежат числовым типам ( int/float/fractionкроме Decimalтипа), они все равно будут работать.
>>> import random
# weights being integers
>>> random.choices(["white", "green", "red"], [12, 12, 4], k=10)
['green', 'red', 'green', 'white', 'white', 'white', 'green', 'white', 'red', 'white']
# weights being floats
>>> random.choices(["white", "green", "red"], [.12, .12, .04], k=10)
['white', 'white', 'green', 'green', 'red', 'red', 'white', 'green', 'white', 'green']
# weights being fractions
>>> random.choices(["white", "green", "red"], [12/100, 12/100, 4/100], k=10)
['green', 'green', 'white', 'red', 'green', 'red', 'white', 'green', 'green', 'green']
2) Если ни веса, ни cum_weights не указаны, выборы делаются с равной вероятностью. Если указана последовательность весов , она должна быть той же длины, что и последовательность совокупности .
Задание весов и cum_weights повышает a TypeError.
>>> random.choices(["white", "green", "red"], k=10)
['white', 'white', 'green', 'red', 'red', 'red', 'white', 'white', 'white', 'green']
3) cum_weights обычно являются результатом itertools.accumulateфункции, которая действительно удобна в таких ситуациях.
Из документации связано:
Внутренне, относительные веса преобразуются в кумулятивные веса, прежде чем делать выбор, поэтому предоставление кумулятивных весов экономит работу.
Таким образом, либо поставка, weights=[12, 12, 4]либо cum_weights=[12, 24, 28]для нашего надуманного дела дает тот же результат, и последний кажется более быстрым / эффективным.
random.choicesдля отдельных вызовов. Если вам нужно много случайных результатов, очень важно выбрать их все сразу, настроивnumber_of_items_to_pick. Если вы это сделаете, это будет на порядок быстрее.