要素をランダムに抽出する関数

要素をランダムに抽出する関数

シーケンスの要素を無作為に抽出する関数

 標準ライブラリの randomモジュール には、シーケンスからランダム (無作為) に要素を抽出する random.choice(), random.sample() があります。NumPyパッケージには配列から複数個の要素をランダムに取り出す numpy.choice() が用意されています。

random.choice()

 random.choice(seq) は引数 seq に渡したシーケンス(文字列、リスト、タプルなど)から要素をランダムに一つ選んで返します(どの要素も等しい確率で選ばれます)。

random.choice(seq)

 以下のコードは、リストから重複を許して 3 回連続で無作為抽出してます。

# PYTHON_RANDOM_CHOICE

# In[1]

# randomモジュールをインポート
import random

# 乱数を初期化
random.seed(0)

# 恒星リスト
stars = ["太陽", "シリウス", "アケルナル", "ベガ", "プロキオン"]

# 恒星リストから3回ランダムに要素を抽出(重複あり)
for k in range(3):
    x = random.choice(stars)
    print(x)

# ベガ
# ベガ
# 太陽

random.sample()

 random.sample() は population に指定したシーケンスまたは集合から k 個の要素を重複なしで抽出して、それらを要素に持つ新しいリストを作成します。

random.sample(population, k)

 以下のコードは set からランダムに要素を抽出してリストを生成します。

# PYTHON_RANDOM_SAMPLE

# In[1]

import random

# 乱数を初期化
random.seed(0)

# 恒星の集合(set)
stars = {"カノープス", "アルタイル", "カペラ", "デネブ", "カストル"}

# 3個の要素をランダムに抽出して新しいリストを作成(重複なし)
y = random.sample(stars, 3)

print(y)
# ['カノープス', 'デネブ', 'カペラ']

 

random.choices()

 random.choices() は population に指定したシーケンスまたは集合から引数 k に指定した個数の要素を重複ありで無作為抽出し、それらを要素に持つ新しいリストを作成します。

random.choices(population, weights=None, cum_weights=None, k=1)

 引数 weights に相対的な重みのシーケンスを渡すと、各要素が選ばれる確率を調整することができます。

# PYTHON_RANDOM_CHOICES

# In[1]

import random

# 乱数を初期化
random.seed(0)

# 恒星リスト
stars = ["アルデバラン", "スピカ", "リゲル", "ベテルギウス", "エルナト"]

# 相対的な重みのリスト
w = [1, 1, 2, 2, 4]

# 各要素に重みwをつけて、5個の要素をランダムに抽出してリストを作成
x = random.choices(stars, k = 5, weights = w)

print(x)
# ['エルナト', 'エルナト', 'ベテルギウス', 'リゲル', 'ベテルギウス']

 上のサンプルコードでは相対的な重みのリストを [1, 1, 2, 2, 4] で指定しています。これによって、たとえばリストの 3 つめの要素(インデックス 2 の要素)"リゲル" は
 
   2/(1+1+2+2+4) = 2/10 = 1/5
 
の確率で選び出されることになります。random.choices() は引数 cum_weights で累積的な重みを指定することもできます (weights と同時に指定することはできません)。サンプルコードは割愛しますが、相対的な重み [1, 1, 2, 2, 4] は、累積的な重み [1, 2, 4, 6, 10] と等価です。

numpy.random.choice()

 numpy.random.choice() は第 1 引数に渡した配列 a から要素を無作為に抽出します。

numpy.random.choice(a, size=None, replace=True, p=None)

 デフォルト設定 (replace=True) では重複を許して取り出します。
 replace は「引いたクジを元に戻す」という意味のキーワードです。

# NUMPY_RANDOM_CHOICE

# In[1]

# NumPyをインポート
import numpy as np

# 乱数シードを設定
np.random.seed(9)

# 恒星のリスト
stars = np.array(["カノープス",
                  "アルタイル",
                  "カペラ",
                  "デネブ",
                  "カストル"])

# リストから6個の要素をランダム抽出(重複あり)
# 戻り値は3行2列の配列
x = np.random.choice(stars, size=(3, 2))

print(x)
# [['カストル' 'カノープス']
#  ['デネブ' 'アルタイル']
#  ['カストル' 'デネブ']]

 replace に Falsee を渡すと、重複なしで抽出します。

# In[2]

np.random.seed(9)

# リストから3個の要素をランダム抽出(重複なし)
# 戻り値は1次元配列
y = np.random.choice(stars, size=3, replace=False)

print(y)
# ['デネブ' 'カノープス' 'アルタイル']

 各要素が抽出される確率を引数 p で指定できます。

# In[3]

np.random.seed(13)

# 各要素の抽出確率を設定
prob = np.array([0.5, 0.2, 0.1, 0.1, 0.1])

# 等確率で8要素を取り出して4行2列で返す
x = np.random.choice(stars, size=(4,2), p=prob)

print(x)
# [['カペラ' 'カノープス']
#  ['デネブ' 'カストル']
#  ['カストル' 'カノープス']
#  ['アルタイル' 'カペラ']]

 a に整数を渡すと、a 未満の正整数のをランダム抽出します。

# In[4]

np.random.seed(15)

# 9以下の整数から無作為に5個の数字を抽出(重複あり)
x = np.random.choice(10, 5)

print(x)
# [8 5 5 7 0]