Pythonでリストなどからランダムで要素を取得する

公開日:2019-05-16
最終更新:2019-05-16

要素のランダム取得

Pythonでリストなどのシーケンスから要素をランダムに取得したい場合は、choice()を利用する。またchoice()は要素を1つだけ取得するが、複数の要素を取得するにはsample()choices()を用いる。違いは取得した要素に重複があるか否か(重複なしがsample())である。

利用について

処理させる際には下記のようにモジュールのインポートが必要。

>>> import random  

コード

choice(seq)

https://docs.python.org/ja/3/library/random.html#random.choice

シーケンスseqからランダムに1つの要素を返す。

>>> list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]  
>>> random.choice(list)  
5  
>>> random.choice(list)  
6  
>>> random.choice(list)  
6  
>>> words = ["hoge", "fuga", "piyo", "foo", "bar", "baz"]  
>>> random.choice(words)  
'bar'  
>>> random.choice(words)  
'foo'  
>>> random.choice(words)  
'baz'  

シーケンスなので文字列に対して処理することもできる。この場合、文字列中の1文字をランダムに取得する。

>>> str = "abcdefg"  
>>> type(str)  
<class 'str'>  
>>> random.choice(str)  
'c'  

seqが空である場合、IndexErrorが返ってくる。

>>> blank = []  
>>> random.choice(blank)  
Traceback (most recent call last):  
  File "<stdin>", line 1, in <module>  
  File "C:\app\Continuum\anaconda3\lib\random.py", line 260, in choice  
    raise IndexError('Cannot choose from an empty sequence') from None  
IndexError: Cannot choose from an empty sequence  

sample(population, k)

https://docs.python.org/ja/3/library/random.html#random.sample

シーケンスpopulationからランダムで複数の要素を重複なしでk個取得する。kが0である場合は、空のリストを返す。

>>> list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]  
>>> random.sample(list, 3)  
[2, 10, 5]  
>>> random.sample(list, 3)  
[1, 8, 4]  
>>> random.sample(list, 3)  
[5, 2, 3]  
>>> words = ["hoge", "fuga", "piyo", "foo", "bar", "baz"]  
>>> random.sample(words, 2)  
['hoge', 'foo']  
>>> random.sample(words, 2)  
['hoge', 'fuga']  
>>> random.sample(words, 2)  
['piyo', 'foo']  
>>> random.sample(words, 0)  
[]  

なお、kで1が指定された場合でも1つの要素がリストで返されるので注意。

>>> words = ["hoge", "fuga", "piyo", "foo", "bar", "baz"]  
>>> select = random.sample(words, 1)  
>>> select  
['bar']  
>>> type(select)  
<class 'list'>  

シーケンスpopulationが空だった場合はエラーになる。

>>> blank = []  
>>> random.sample(blank, 2)  
Traceback (most recent call last):  
  File "<stdin>", line 1, in <module>  
  File "C:\app\Continuum\anaconda3\lib\random.py", line 320, in sample  
    raise ValueError("Sample larger than population or is negative")  
ValueError: Sample larger than population or is negative  

choices(population, weights=None, *, cum_weights=None, k=1)

https://docs.python.org/ja/3/library/random.html#random.choices

シーケンスpopulationからランダムで複数の要素を重複ありでk個取得する。kが省略された場合のデフォルトは1。この場合、1つの要素がリストで返される

weightsおよびcum_weightsが与えられなかった場合、要素は同じ確率で選択される。weightsシーケンスが与えられた場合、相対的な重みに基づいて要素が選ばれる。あるいは、cum_weightsシーケンスが与えられた場合、累積的な重みで要素が選ばれる。例えば、weights[10, 5, 30, 5]はcum_weights[10, 15, 45, 50]と等価である。weightsあるいはcum_weightsのシーケンスの長さは、populationと同じでなければならない。

内部的には、相対的な重みは要素選択の前に累積的な重みに変換されるため、累積的な重みを渡すと手間を省けます。

>>> words = ["hoge", "fuga", "piyo", "foo", "bar", "baz"]  
>>> random.choices(words)  
['baz']  
>>> random.choices(words, k=5)  
['baz', 'bar', 'foo', 'hoge', 'piyo']  
>>> random.choices(words, k=5)  
['foo', 'fuga', 'foo', 'hoge', 'hoge']  
>>> random.choices(words, k=5)  
['baz', 'piyo', 'foo', 'bar', 'baz']  
>>> weights = [20, 15, 15, 10, 10, 30]  
>>> random.choices(words, weights, k=5)  
['baz', 'fuga', 'piyo', 'baz', 'bar']  
>>> random.choices(words, weights, k=5)  
['hoge', 'foo', 'fuga', 'hoge', 'foo']  
>>> random.choices(words, weights, k=5)  
['baz', 'foo', 'piyo', 'piyo', 'fuga']  
>>> random.choices(words, cum_weights=weights, k=5)  
['hoge', 'baz', 'hoge', 'baz', 'baz']  
>>> random.choices(words, cum_weights=weights, k=5)  
['hoge', 'hoge', 'hoge', 'hoge', 'baz']  
>>> random.choices(words, cum_weights=weights, k=5)  
['hoge', 'baz', 'hoge', 'hoge', 'hoge']  

なお、weightsとcum_weightsを同時に与えるとTypeErrorを返す。

>>> random.choices(words, weights=weights, cum_weights=weights, k=5)  
Traceback (most recent call last):  
  File "<stdin>", line 1, in <module>  
  File "C:\app\Continuum\anaconda3\lib\random.py", line 358, in choices  
    raise TypeError('Cannot specify both weights and cumulative weights')  
TypeError: Cannot specify both weights and cumulative weights  

populationが空だった場合はエラーになる。

>>> blank=[]  
>>> random.choices(blank, k=5)  
Traceback (most recent call last):  
  File "<stdin>", line 1, in <module>  
  File "C:\app\Continuum\anaconda3\lib\random.py", line 355, in choices  
    return [population[_int(random() * total)] for i in range(k)]  
  File "C:\app\Continuum\anaconda3\lib\random.py", line 355, in <listcomp>  
    return [population[_int(random() * total)] for i in range(k)]  
IndexError: list index out of range  
>>> random.choices(blank, cum_weights=weights, k=5)  
Traceback (most recent call last):  
  File "<stdin>", line 1, in <module>  
  File "C:\app\Continuum\anaconda3\lib\random.py", line 360, in choices  
    raise ValueError('The number of weights does not match the population')  
ValueError: The number of weights does not match the population  

なお、sample()とは異なり、kは指定する際にはk=3などと記述する必要がある(単純に数字だけ指定してはいけない)。

>>> random.choices(words, weights, k=5)  
['hoge', 'fuga', 'baz', 'hoge', 'hoge']  
>>> random.choices(words, weights, 5)  
Traceback (most recent call last):  
  File "<stdin>", line 1, in <module>  
TypeError: choices() takes from 2 to 3 positional arguments but 4 were given  
記事が少しでもいいなと思ったらクラップを送ってみよう!
10
+1
@webmaster909の技術ブログ

よく一緒に読まれている記事

0件のコメント

ブログ開設 or ログイン してコメントを送ってみよう
目次をみる

技術ブログをはじめよう

Qrunch(クランチ)は、ITエンジニアリングに携わる全ての人のための技術ブログプラットフォームです。

技術ブログを開設する

Qrunchでアウトプットをはじめよう

Qrunch(クランチ)は、ITエンジニアリングに携わる全ての人のための技術ブログプラットフォームです。

Markdownで書ける

ログ機能でアウトプットを加速

デザインのカスタマイズが可能

技術ブログ開設

ここから先はアカウント(ブログ)開設が必要です

英数字4文字以上
.qrunch.io
英数字6文字以上
ログインする