Выбор, выборка и варианты для случайного выбора элементов из списка в Python.

Бизнес

Функции choice(), sample() и choices() модуля random стандартной библиотеки Python можно использовать для случайного выбора и извлечения элементов из списка, кортежа, строки или другого объекта последовательности (случайная выборка).

choice() получает один элемент, sample() и choices() получают список из нескольких элементов. sample() — это невосстанавливаемое извлечение без дубликатов, choices() — восстанавливаемое извлечение с дубликатами.

Здесь представлена следующая информация.

  • Выберите один элемент наугад.: random.choice()
  • Случайный выбор нескольких элементов (без дубликатов): random.sample()
  • Случайный выбор нескольких элементов (с дубликатами): random.choices()
  • Зафиксируйте затравку случайного числа

Выберите один элемент наугад.: random.choice()

С помощью функции select() модуля random из списка случайным образом выбирается один элемент, который можно извлечь.

import random

l = [0, 1, 2, 3, 4]

print(random.choice(l))
# 1

То же самое относится к кортежам и строкам. В случае со строками выбирается один символ.

print(random.choice(('xxx', 'yyy', 'zzz')))
# yyy

print(random.choice('abcde'))
# b

Ошибка, если в качестве аргумента указан пустой список, кортеж или строка.

# print(random.choice([]))
# IndexError: Cannot choose from an empty sequence

Случайный выбор нескольких элементов (без дубликатов): random.sample()

С помощью функции sample() модуля random можно получить несколько элементов случайным образом из списка. При этом дублирование элементов (безвозвратное извлечение) не происходит.

Первым аргументом является список, а вторым — количество элементов, которые необходимо извлечь. Возвращается список.

import random

l = [0, 1, 2, 3, 4]

print(random.sample(l, 3))
# [2, 4, 0]

print(type(random.sample(l, 3)))
# <class 'list'>

Если второй аргумент равен 1, возвращается список с одним элементом; если он равен 0, список пуст. Если второй аргумент равен 1, возвращается список с одним элементом; если он равен 0, возвращается пустой список; если первый аргумент больше количества элементов в списке, возникает ошибка.

print(random.sample(l, 1))
# [3]

print(random.sample(l, 0))
# []

# print(random.sample(l, 10))
# ValueError: Sample larger than population or is negative

Если первым аргументом является кортеж или строка, то возвращается все равно список.

print(random.sample(('xxx', 'yyy', 'zzz'), 2))
# ['xxx', 'yyy']

print(random.sample('abcde', 2))
# ['b', 'e']

Если вы хотите вернуться к кортежу или строке, используйте tuple(),join().

print(tuple(random.sample(('xxx', 'yyy', 'zzz'), 2)))
# ('xxx', 'yyy')

print(''.join(random.sample('abcde', 2)))
# dc

Обратите внимание, что значение не оценивается, поэтому если исходный список или кортеж содержит элементы с одинаковым значением, есть вероятность, что будет выбрано то же значение.

l_dup = [0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3]

print(random.sample(l_dup, 3))
# [3, 1, 1]

Если вы хотите избежать дублирования значений, вы можете использовать set(), чтобы преобразовать его в набор (тип set) и извлечь только уникальные элементы, а затем использовать sample().

print(set(l_dup))
# {0, 1, 2, 3}

print(random.sample(set(l_dup), 3))
# [1, 3, 2]

Случайный выбор нескольких элементов (с дубликатами): random.choices()

Функция choices() модуля random позволяет получить несколько элементов из списка случайным образом, и, в отличие от sample(), она позволяет выбирать дубликаты элементов.

choices() — это функция, добавленная в Python 3.6. Она недоступна в более ранних версиях.

Аргумент k задает количество элементов, которые будут извлечены. Дублирование разрешено, поэтому количество извлекаемых элементов может быть больше, чем количество элементов в исходном списке.

Поскольку k является аргументом только для ключевого слова, необходимо указать ключевое слово, например, 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 равно 1; если оно опущено, возвращается список с 1 элементом.

print(random.choices(l))
# [1]

Аргумент weights может быть использован для указания веса (вероятности) того, что каждый элемент будет выбран, а тип элементов в списке может быть int или float.

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]

Аргумент cum_weights также может быть указан как кумулятивный вес. Значение cum_weights в следующем примере кода эквивалентно первому весу, указанному выше.

print(random.choices(l, k=3, cum_weights=[1, 2, 3, 13, 14]))
# [3, 2, 3]

По умолчанию для аргументов weights и cum_weights установлено значение None, что означает, что каждый элемент выбирается с одинаковой вероятностью.

Если длина (количество элементов) аргумента weights или cum_weights отличается от исходного списка, возникает ошибка.

# print(random.choices(l, k=3, weights=[1, 1, 1, 10, 1, 1, 1]))
# ValueError: The number of weights does not match the population_

Также ошибкой является одновременное указание весов и cum_weights.

# 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

До сих пор в коде примера в качестве первого аргумента мы указывали список, но то же самое относится к кортежам и строкам.

Зафиксируйте затравку случайного числа

Задав произвольное целое число функции seed() модуля random, можно зафиксировать семя случайного числа и инициализировать генератор случайных чисел.

После инициализации одним и тем же семенем элементы всегда выбираются одинаковым образом.

random.seed(0)
print(random.choice(l))
# 3

random.seed(0)
print(random.choice(l))
# 3