Python♪randomモジュールの基本的な使い方

チュートリアル「10. 標準ライブラリミニツアー 10.6.数学」に出てくるrandomモジュールの関数を整理してみました。randomモジュールには、他にも、便利な関数が多くありますが、まずは、この記事に出てくる関数から覚えてはいかがでしょうか。

なお、random.choices()はチュートリアルでは出てきませんが、重複を許さないrandom.sample()に対して、重複を許す関数として、比較のために説明に加えました。

0.チュートリアル学習のポイントシリーズ

この記事は「チュートリアル学習のポイントシリーズ」の記事です。一連の記事のリンクは、以下を参照してください。
Pythonチュートリアルの学習のポイントを整理

1.randomモジュールの基本的な関数

それでは、以下、関数の簡単な解説とサンプルコードを紹介したいと思います。なお、最初は違いが分かりにくいと思いますので、以下の点に注目して読み進めてください。

 ①ランダムな結果を1つだけ返すのか、それとも複数選択しlistで返すのか。
 ②複数選択できる場合、同じものを重複して選択できるのか。

「random.choice(s)」などは、例えば['a', 'b', 'c']などを与えると、この中から結果を1つだけ返しますが、以下の関数はランダムに複数の要素を選択し、選んだ複数の要素をlist型で返します。
 「random.choices(s, k = i)」→要素の重複選択が可能
 「random.sample(p, i)」→要素の重複選択は不可

また、「random.choices(s, k = i)」は、choicesの最後に「s」がついていることに注意し、「k = 」を忘れないようにしましょう。

それでは、random.choice(s)から説明します。

(1) random.choice(s)

空でないシーケンス s からランダムに要素を1つだけ返します。
(s が空のときは、 IndexError が送出されます。)

呼び出し:import random

s: シーケンス型
戻り値: ランダムに選択したsの要素

なお、 複数の要素を順番に並べたデータ型がシーケンス型に分類されています。 順番の概念がないディクショナリ型や集合型はシーケンスではありません。

 サンプルコード
#コード
import random

x = random.choice(['a', 'b', 'c'])
print('リスト:', x)
x = random.choice(('a', 'b', 'c'))
print('タプル:', x)
x = random.choice(('abc'))
print('文字列:', x)
x = random.choice(range(10))
print('rangeオブジェクト:', x)
#出力
リスト: b
タプル: b
文字列: a
rangeオブジェクト: 7

(2) random.choices(s, k = i)

呼び出し:import random

シーケンスsから重複ありで、i回要素を選び、大きさiのリストを返す。
(sが空で、kが1以上の場合には、IndexError が送出されます。)

s: シーケンス型 ※集合型やディクショナリ型などはシーケンス型ではない。
i: int型(整数)
戻り値: sよりランダムにi個選んだ要素のリスト(重複あり)

 サンプルコード
#コード
import random

x = random.choices(['a','b','c'], k = 5)
print('リスト:', x)
x = random.choices(('a','b','c'), k = 5)
print('タプル:', x)
x = random.choices('abc', k = 5)
print('文字列:', x)
x = random.choices(range(10), k = 5)
print('rangeオブジェクト:', x)
#出力
リスト: ['a', 'c', 'b', 'c', 'a']
タプル: ['b', 'b', 'a', 'b', 'b']
文字列: ['b', 'b', 'b', 'a', 'b']
rangeオブジェクト: [7, 9, 2, 7, 9]

(3) random.sample(p, i)

シーケンスまたは集合型(set型)であるpから重複なしでi回要素を選び、大きさiのリストを返す。
(サンプルの大きさが母集団の大きさより大きい場合 ValueError が送出されます。)

呼び出し:import random

p: シーケンス型、集合型(set型) ※ディクショナリ型等は指定できない。
戻り値: pよりランダムにi個選んだ要素のリスト(重複なし)

 サンプルコード
#コード
import random

x = random.sample(['a','b','c'], 2)
print('リスト:', x)
x = random.sample(('a','b','c'), 2)
print('タプル:', x)
x = random.sample('abc', 2)
print('文字列:', x)
x = random.sample(range(10), 2)
print('rangeオブジェクト:', x)
x = random.sample({'a','b','c'}, 2)
print('集合:', x)
#出力
リスト: ['c', 'b']
タプル: ['b', 'a']
文字列: ['a', 'c']
rangeオブジェクト: [3, 5]
集合: ['a', 'b']

(4) random.randrange( )

random.randrange(stop)

0以上、(stop-1)以下の整数をランダムに1つだけ返す。
(例えばrandom.randrange(5)は、0, 1, 2, 3, 4の中からランダムに1つ選びます。)

呼び出し:import random

stop:整数
戻り値: 0以上、(stop-1)以下の整数

random.randrange(start, stop)

start以上、(stop-1)以下の整数をランダムに1つだけ返す。
(例えばrandom.randrange(2, 5)は、2, 3, 4の中からランダムに1つ選びます。)

呼び出し:import random

start:整数
stop:整数
戻り値: start以上、(stop-1)以下の整数 (重複あり)

random.randrange(start, stop, step)

rangeオブジェクトと同様に、startとstopだけではなく、増分(step)も指定できる。増分も考慮した整数の中から、ランダムに選んだ値を1つだけ返す。
(例えばrandom.randrange(2, 8, 3)は、2, 5からランダムに1つ選びます。)

呼び出し:import random

start:整数
stop:整数
step:整数
戻り値:増分(step)も考慮した start以上、(stop-1)以下の整数

 サンプルコード
#コード
for i in range(10):
    x = random.randrange(2, 8, 3)
    print(x)
#出力
2
5
5
5
5
5
5
2
5
5

(5) random.random()

0.0以上、1.0未満のランダムな浮動小数点数を返す。
※1.0以下ではなく、1.0未満であることに注意。つまり、1.0は入らない。

呼び出し:import random

戻り値:0.0以上、1.0未満のランダムな浮動小数点数

 サンプルコード
#コード
import random

for i in range(10):
    x = random.random()
    print(x)
#出力
0.8872005109749738
0.4263030243562481
0.414463816514999
0.7771672637108323
0.9714283384522235
0.5959627270544248
0.14622803917429827
0.6469840724897818
0.3422950442864625
0.7395873707916015

2. random.choices() の応用的な使い方

random.choices()では、各要素を均等な割合で選ぶだけではなく、それぞれの要素を選ぶ割合を指定することができます。便利ですので、「こんなことができる」ということだけ知っておいてください。

(1) random.choices(s, weights = list, k = i)

呼び出し:import random

シーケンスsから重複ありで、i回要素を選び、大きさiのリストを返す。sが空で、kが1以上の場合には、IndexError が送出されます。要素を選ぶときにlistで、選ぶ割合(相対的な割合)を指定できます。
例えばrandom.choices(['a', 'b', 'c'], weights = [5, 2, 3], k=10000)では、'a', 'b', 'c'が選択される割合は5 : 2 : 3となります。

s: シーケンス型 ※シーケンス型ではない集合型やディクショナリ型などは選択できない。
list:リスト型(タプル型でもエラーにはならない)
i: int型(整数)
戻り値: sよりランダムにi個選んだ要素のリスト(重複あり)

 サンプルコード
#コード
import random

n = 100000
sa = 0
sb = 0
sc = 0

x = random.choices(['a','b','c'], weights = (5, 2, 3), k = n)

for i in range(n):
    if x[i] == 'a':
        sa = sa + 1
    if x[i] == 'b':
        sb = sb + 1
    if x[i] == 'c':
        sc = sc + 1

ss = sa + sb + sc
print('選択回数:',n)
print('aの割合', sa / ss)
print('bの割合', sb / ss)
print('cの割合', sc / ss)
#出力
選択回数: 100000
aの割合 0.50303
bの割合 0.19773
cの割合 0.29924

(2) random.choices(s, cum_weights = list, k = i)

cum_weights = listは、相対的な割合ではなく、累積的な割合を指定します。例えば
weights = [5, 2, 3]は、cum_ weights = [5, 7, 10]と同じです。 5 + 2 = 7であり、5 + 2 + 3 = 10です。

weightsの方が直感的でわかりやすいですが、内部的には、相対的な割合は要素選択の前に累積的な割合に変換されるため、累積的な割合の方が多少計算が速いです。