As funções escolha(), amostra(), e escolhas() no módulo aleatório da biblioteca padrão Python podem ser usadas para seleccionar e recuperar aleatoriamente elementos de uma lista, tuple, string, ou outro objecto sequencial (amostragem aleatória).
escolha() obtém um único elemento, amostra() e escolhas() obtém uma lista de múltiplos elementos. amostra() é extracção não recuperável sem duplicados, escolhas() é extracção recuperável com duplicados.
A seguinte informação é fornecida aqui.
- Seleccionar um elemento ao acaso.:
random.choice()
- Seleccionar aleatoriamente múltiplos elementos (sem duplicados):
random.sample()
- Seleccionar aleatoriamente múltiplos elementos (com duplicados):
random.choices()
- Fixar o número aleatório de sementes
Seleccionar um elemento ao acaso.: random.choice()
Com a função do módulo aleatório escolher(), um elemento é seleccionado aleatoriamente a partir da lista e pode ser recuperado.
import random
l = [0, 1, 2, 3, 4]
print(random.choice(l))
# 1
O mesmo se aplica aos tufos e cordas. No caso das cordas, é seleccionado um único carácter.
print(random.choice(('xxx', 'yyy', 'zzz')))
# yyy
print(random.choice('abcde'))
# b
Erro se uma lista vazia, tuple, ou string for especificada como argumento.
# print(random.choice([]))
# IndexError: Cannot choose from an empty sequence
Seleccionar aleatoriamente múltiplos elementos (sem duplicados): random.sample()
Com a função amostra() do módulo aleatório, é possível obter múltiplos elementos ao acaso a partir de uma lista. Não há duplicação de elementos (extracção não recuperável).
O primeiro argumento é uma lista, e o segundo argumento é o número de elementos a serem recuperados. A lista é devolvida.
import random
l = [0, 1, 2, 3, 4]
print(random.sample(l, 3))
# [2, 4, 0]
print(type(random.sample(l, 3)))
# <class 'list'>
Se o segundo argumento for fixado em 1, é também devolvida uma lista com um elemento; se for fixado em 0, a lista está vazia. Se o segundo argumento for 1, é devolvida uma lista com um elemento; se for 0, é devolvida uma lista vazia; se o primeiro argumento for mais do que o número de elementos da lista, ocorre um erro.
print(random.sample(l, 1))
# [3]
print(random.sample(l, 0))
# []
# print(random.sample(l, 10))
# ValueError: Sample larger than population or is negative
Se o primeiro argumento for um tuple ou um fio, o que é devolvido continua a ser uma lista.
print(random.sample(('xxx', 'yyy', 'zzz'), 2))
# ['xxx', 'yyy']
print(random.sample('abcde', 2))
# ['b', 'e']
Se quiser regressar a um tuple ou string, use tuple(),join().
print(tuple(random.sample(('xxx', 'yyy', 'zzz'), 2)))
# ('xxx', 'yyy')
print(''.join(random.sample('abcde', 2)))
# dc
Note-se que o valor não é julgado, portanto se a lista original ou tuple contém elementos com o mesmo valor, há a possibilidade de que o mesmo valor seja seleccionado.
l_dup = [0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3]
print(random.sample(l_dup, 3))
# [3, 1, 1]
Se quiser evitar a duplicação de valores, pode usar set() para convertê-lo num conjunto (set type) e extrair apenas os elementos únicos, e depois usar sample().
print(set(l_dup))
# {0, 1, 2, 3}
print(random.sample(set(l_dup), 3))
# [1, 3, 2]
Seleccionar aleatoriamente múltiplos elementos (com duplicados): random.choices()
As escolhas de função do módulo aleatório() permite recuperar múltiplos elementos aleatoriamente de uma lista, e ao contrário da amostra(), permite seleccionar elementos duplicados.
escolhas() é uma função adicionada em Python 3.6. Não está disponível em versões anteriores.
O argumento k especifica o número de elementos a serem recuperados. A duplicação é permitida, pelo que o número de elementos a serem recuperados pode ser maior do que o número de elementos da lista original.
Uma vez que k é um argumento apenas de palavras-chave, é necessário especificar uma palavra-chave, tal como 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]
O valor por defeito de k é 1; se for omitido, é devolvida uma lista com 1 elemento.
print(random.choices(l))
# [1]
Os pesos dos argumentos podem ser utilizados para especificar o peso (probabilidade) que cada elemento será seleccionado, e o tipo dos elementos da lista pode ser int ou 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]
O argumento cum_weights também pode ser especificado como um peso cumulativo. O peso cum_weights no seguinte código de amostra é equivalente aos primeiros pesos acima.
print(random.choices(l, k=3, cum_weights=[1, 2, 3, 13, 14]))
# [3, 2, 3]
O padrão para ambos os pesos de argumentos e cum_weights é Nenhum, o que significa que cada elemento é seleccionado com a mesma probabilidade.
Se o comprimento (número de elementos) dos pesos dos argumentos ou cum_weights for diferente da lista original, ocorre um erro.
# print(random.choices(l, k=3, weights=[1, 1, 1, 10, 1, 1, 1]))
# ValueError: The number of weights does not match the population_
É também um erro especificar pesos e pesos cum_weights ao mesmo tempo.
# 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
Especificámos uma lista como primeiro argumento como exemplo no código da amostra até agora, mas o mesmo se aplica aos tuplos e cordas.
Fixar o número aleatório de sementes
Ao dar um inteiro arbitrário à função semente() do módulo aleatório, a semente do número aleatório pode ser fixada e o gerador de números aleatórios pode ser inicializado.
Após a inicialização com a mesma semente, os elementos são sempre seleccionados da mesma forma.
random.seed(0)
print(random.choice(l))
# 3
random.seed(0)
print(random.choice(l))
# 3