チュートリアル「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の方が直感的でわかりやすいですが、内部的には、相対的な割合は要素選択の前に累積的な割合に変換されるため、累積的な割合の方が多少計算が速いです。