Начиная с 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
type), они все равно будут работать.
>>> 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 , выбор выполняется с равной вероятностью. Если указана последовательность weights , она должна быть такой же длины, что и последовательность population .
Указание весов и cum_weights повышает 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]
для нашего надуманного дела дает тот же результат, и последний кажется более быстрым / эффективным.