228 views
この記事は最終更新から 397日 が経過しています。
【1】やりたいこと
Pythonで乱数を生成したい。
ただし、以下の条件を満たすこと。
・重複しないこと
・一様分布であること
【2】やってみる
1) numpyを使わない場合
まずは、普通に乱数を生成してみる。
>>> import random >>> >>> [random.randint(1, 100) for _ in range(5)] [54, 28, 87, 63, 62] >>> [random.randint(1, 5) for _ in range(3)] [2, 4, 5] >>> [random.randint(1, 5) for _ in range(3)] [5, 1, 2] >>> [random.randint(1, 5) for _ in range(3)] [1, 2, 5] >>> [random.randint(1, 5) for _ in range(3)] [4, 4, 4]
重複する可能性がある。
重複を回避するには random.sample を使う。
>>> random.sample([1,2,3,4,5], 3) [2, 3, 4] >>> random.sample([1,2,3,4,5], 3) [2, 3, 5] >>> random.sample([1,2,3,4,5], 3) [3, 5, 1] >>> random.sample([1,2,3,4,5], 3) [2, 4, 3] >>> random.sample([1,2,3,4,5], 3) [1, 2, 4] >>> random.sample([1,2,3,4,5], 3) [3, 1, 2] >>> random.sample([1,2,3,4,5], 3) [2, 4, 5] >>> random.sample([1,2,3,4,5], 3) [5, 1, 4] >>> random.sample([1,2,3,4,5], 3) [4, 1, 2] >>> random.sample([1,2,3,4,5], 3) [5, 4, 2]
重複しない。
念のために 1~5の範囲で 5個の乱数を生成させてみる。
>>> random.sample([1,2,3,4,5], 5) [4, 5, 3, 1, 2] >>> random.sample([1,2,3,4,5], 5) [5, 4, 2, 3, 1] >>> random.sample([1,2,3,4,5], 5) [4, 2, 1, 3, 5] >>> random.sample([1,2,3,4,5], 5) [5, 2, 3, 1, 4] >>> random.sample([1,2,3,4,5], 5) [1, 3, 2, 4, 5] >>> random.sample([1,2,3,4,5], 5) [5, 2, 1, 4, 3] >>> random.sample([1,2,3,4,5], 5) [4, 3, 5, 1, 2] >>> random.sample([1,2,3,4,5], 5) [5, 1, 3, 4, 2] >>> random.sample([1,2,3,4,5], 5) [3, 4, 1, 5, 2] >>> random.sample([1,2,3,4,5], 5) [3, 1, 2, 4, 5]
確かに重複しない!
範囲が大きい場合は range を使えばよい。
>>> random.sample(range(1,1000), 5) [582, 820, 778, 67, 785] >>> random.sample(range(1,1000), 5) [602, 27, 896, 161, 186] >>> random.sample(range(1,1000), 5) [220, 284, 887, 182, 905]
2) numpyを使う場合
まずは普通に整数乱数を生成してみる。
>>> import numpy as np >>> >>> np.random.randint(1,5,3) array([1, 4, 1])
いきなり重複した。
重複を回避するには numpy.random.choice を replace=False 指定で使う。
>>> np.random.choice([1,2,3,4,5], 3, replace=False) array([3, 2, 5]) >>> np.random.choice([1,2,3,4,5], 3, replace=False) array([2, 4, 3]) >>> np.random.choice([1,2,3,4,5], 3, replace=False) array([4, 2, 1]) >>> np.random.choice([1,2,3,4,5], 5, replace=False) array([3, 2, 4, 1, 5]) >>> np.random.choice([1,2,3,4,5], 5, replace=False) array([5, 4, 3, 1, 2]) >>> np.random.choice([1,2,3,4,5], 5, replace=False) array([2, 4, 3, 1, 5]) >>> np.random.choice([1,2,3,4,5], 5, replace=False) array([2, 1, 4, 3, 5]) >>> np.random.choice([1,2,3,4,5], 5, replace=False) array([2, 1, 4, 3, 5])
重複しない。
範囲が大きい場合は range を使えばよい。
>>> np.random.choice(range(1,1000), 3, replace=False) array([139, 356, 666]) >>> np.random.choice(range(1,1000), 3, replace=False) array([304, 3, 512]) >>> np.random.choice(range(1,1000), 3, replace=False) array([247, 752, 744]) >>> np.random.choice(range(1,1000), 3, replace=False) array([976, 821, 382]) >>> np.random.choice(range(1,1000), 3, replace=False) array([960, 376, 934])
replace=False を外すと重複する可能性がある。
>>> np.random.choice([1,2,3,4,5], 3) array([1, 5, 3]) >>> np.random.choice([1,2,3,4,5], 3) array([2, 2, 4])
重複した。
【3】応用
(1) 配列の中からランダムに要素を抽出したい。
配列を作る。
>>> import numpy as np >>> >>> a = np.random.randint(100, 999, [5,2]) >>> a array([[846, 394], [166, 615], [380, 439], [390, 236], [853, 882]])
配列要素を指し示す indexを乱数で作る。
>>> i = np.random.choice(range(5), 3, replace=False) >>> i array([2, 4, 0])
indexで指定した配列要素だけを抽出し、新しい配列を作る。
>>> c = a[i] >>> c array([[380, 439], [853, 882], [846, 394]])
使うたびに思うけど、これが便利だなぁ…