Python Random:乱数、選択、サンプルの生成
Updated on
ランダムデータの生成はプログラミングの基本です -- プレイリストのシャッフルやアンケート回答者のサンプリングから、モンテカルロシミュレーションやテストデータセットの作成まで。しかし、Pythonのrandomモジュールには数十の関数があり、間違った関数を使いがちです。整数が必要な時にrandom.random()を呼んだり、複数のユニークな要素が必要な時にchoice()を使ったり、randomが暗号学的に安全でないことを忘れると、微妙なバグやセキュリティの脆弱性につながります。
Pythonのrandomモジュールは、擬似乱数生成のための包括的なツールキットを提供します。このガイドでは、よく使う関数を、いつ使うべきかを示す明確な例とともにすべて解説します。
ランダムな整数
randint(a, b)
a <= N <= b(両端を含む)の範囲でランダムな整数Nを返します。
import random
# Random integer between 1 and 10 (inclusive)
print(random.randint(1, 10)) # e.g., 7
# Simulate a dice roll
dice = random.randint(1, 6)
print(f"You rolled a {dice}")
# Generate random ages for test data
ages = [random.randint(18, 65) for _ in range(5)]
print(ages) # e.g., [34, 52, 21, 45, 28]randrange(start, stop, step)
range()と同様ですが、ランダムな要素を返します。stop値は含まれません。
import random
# Random even number between 0 and 100
print(random.randrange(0, 101, 2)) # e.g., 42
# Random number from 0 to 9
print(random.randrange(10)) # e.g., 7
# Random multiple of 5 from 0 to 100
print(random.randrange(0, 101, 5)) # e.g., 35ランダムな浮動小数点数
random()
[0.0, 1.0)の範囲でランダムな浮動小数点数を返します。
import random
print(random.random()) # e.g., 0.7234...
# Scale to any range: random float between 10 and 20
value = 10 + random.random() * 10
print(value) # e.g., 15.23...uniform(a, b)
a <= N <= bのランダムな浮動小数点数Nを返します。
import random
# Random temperature between 98.0 and 99.5
temp = random.uniform(98.0, 99.5)
print(f"Temperature: {temp:.1f}F") # e.g., Temperature: 98.7F
# Random price between 9.99 and 29.99
price = round(random.uniform(9.99, 29.99), 2)
print(f"Price: ${price}")gauss(mu, sigma) -- 正規分布
import random
# Generate normally distributed values (mean=100, std=15)
iq_scores = [round(random.gauss(100, 15)) for _ in range(10)]
print(iq_scores) # e.g., [112, 95, 103, 88, 107, ...]ランダムな選択
choice(seq)
空でないシーケンスからランダムに1つの要素を返します。
import random
colors = ['red', 'blue', 'green', 'yellow', 'purple']
print(random.choice(colors)) # e.g., 'green'
# Random character from a string
print(random.choice('abcdefghij')) # e.g., 'f'choices(population, weights, k)
復元抽出(重複可能)でk個の要素のリストを返します。重み付けをサポートします。
import random
# Pick 5 random colors (duplicates allowed)
colors = ['red', 'blue', 'green']
print(random.choices(colors, k=5)) # e.g., ['blue', 'red', 'blue', 'green', 'red']
# Weighted selection (red is 5x more likely)
weighted = random.choices(
['red', 'blue', 'green'],
weights=[5, 1, 1],
k=10
)
print(weighted) # Mostly 'red'sample(population, k)
非復元抽出(重複なし)でk個のユニークな要素を返します。
import random
# Lottery numbers: 6 unique numbers from 1-49
lottery = random.sample(range(1, 50), 6)
print(sorted(lottery)) # e.g., [3, 12, 27, 33, 41, 48]
# Random survey sample
employees = ['Alice', 'Bob', 'Charlie', 'Diana', 'Eve', 'Frank']
survey_group = random.sample(employees, 3)
print(survey_group) # e.g., ['Diana', 'Alice', 'Frank']choice vs choices vs sample
| 関数 | 復元 | 返り値 | 用途 |
|---|---|---|---|
choice(seq) | N/A(単一要素) | 1要素 | ランダムに1つ選ぶ |
choices(pop, k=n) | 復元抽出 | n要素のリスト | 重み付きランダム、シミュレーション |
sample(pop, k=n) | 非復元抽出 | n個のユニーク要素のリスト | 抽選、ランダムな部分集合 |
シャッフル
shuffle(seq)
リストをインプレースでシャッフルします。Noneを返します。
import random
deck = list(range(1, 53)) # 52 cards
random.shuffle(deck)
print(deck[:5]) # e.g., [37, 12, 48, 3, 21]
# Deal 5 cards
hand = deck[:5]
remaining = deck[5:]シードと再現性
シードを設定すると、ランダム出力が再現可能になります -- テストやデバッグに不可欠です。
import random
random.seed(42)
print(random.randint(1, 100)) # Always 81
print(random.random()) # Always 0.0744...
# Reset seed for same sequence
random.seed(42)
print(random.randint(1, 100)) # 81 again
print(random.random()) # 0.0744... againシードを使うタイミング
| シナリオ | シード? | 理由 |
|---|---|---|
| ユニットテスト | はい | 再現可能なテスト結果 |
| デバッグ | はい | 正確なバグの再現 |
| シミュレーション(分析) | はい | 再現可能な実験 |
| ゲーム(ゲームプレイ) | いいえ | プレイヤーは真のランダム性を期待 |
| セキュリティ/暗号 | いいえ(secretsを使用) | シードは出力を予測可能にする |
テストデータの生成
import random
import string
def random_string(length=10):
"""Generate a random alphanumeric string."""
chars = string.ascii_letters + string.digits
return ''.join(random.choices(chars, k=length))
def random_email():
"""Generate a random email address."""
name = random_string(8).lower()
domains = ['gmail.com', 'yahoo.com', 'outlook.com']
return f"{name}@{random.choice(domains)}"
def random_user():
"""Generate a random user record."""
first_names = ['Alice', 'Bob', 'Charlie', 'Diana', 'Eve']
last_names = ['Smith', 'Jones', 'Brown', 'Wilson', 'Taylor']
return {
'name': f"{random.choice(first_names)} {random.choice(last_names)}",
'email': random_email(),
'age': random.randint(18, 65),
'score': round(random.uniform(0, 100), 1),
}
# Generate 5 test users
users = [random_user() for _ in range(5)]
for user in users:
print(user)Randomとデータサイエンス
データ分析ワークフローでは、randomモジュールはサンプリング、ブートストラップ、合成データセットの作成に役立ちます。pandasと組み合わせると、テスト用のDataFrameを素早く生成できます:
import random
import pandas as pd
random.seed(42)
n = 1000
df = pd.DataFrame({
'age': [random.randint(18, 80) for _ in range(n)],
'income': [round(random.gauss(50000, 15000), 2) for _ in range(n)],
'category': random.choices(['A', 'B', 'C'], weights=[5, 3, 2], k=n),
})
print(df.describe())ランダムデータセットのインタラクティブな探索には、PyGWalker (opens in a new tab)がpandasのDataFrameをJupyter内でTableauスタイルの可視化UIに変換します:
import pygwalker as pyg
walker = pyg.walk(df)セキュリティ警告:random vs secrets
randomモジュールはセキュリティ目的には適していません。シードが知られている場合、出力は決定的で予測可能です。パスワード、トークン、暗号アプリケーションにはsecretsモジュールを使用してください:
import secrets
# Cryptographically secure random token
token = secrets.token_hex(16)
print(token) # e.g., 'a3f2b8c9d1e4f5a6b7c8d9e0f1a2b3c4'
# Secure random integer
secure_int = secrets.randbelow(100)
# Secure random choice
secure_choice = secrets.choice(['option1', 'option2', 'option3'])| 特徴 | random | secrets |
|---|---|---|
| アルゴリズム | メルセンヌ・ツイスター(PRNG) | OSエントロピーソース(CSPRNG) |
| 決定的 | はい(シード使用時) | いいえ |
| 速度 | 高速 | 低速 |
| 用途 | シミュレーション、ゲーム、テスト | パスワード、トークン、暗号 |
| 再現可能 | はい(seed()使用時) | いいえ |
FAQ
Pythonでランダムな整数を生成するには?
random.randint(a, b)を使って、aからb(両端を含む)のランダムな整数を取得します。例えば、random.randint(1, 10)は1から10の数を返します。上限を除外する範囲には、random.randrange(start, stop)を使用します。
random.choiceとrandom.sampleの違いは?
random.choice(seq)は1つのランダムな要素を返します。random.sample(population, k)は非復元でk個のユニークな要素を返します。重複を許可して複数の要素を選択するには、random.choices(population, k=n)を使用します。
ランダムな結果を再現可能にするには?
乱数を生成する前にrandom.seed(value)を呼び出します。同じシードを使用すると、毎回同じ乱数列が生成されます。ユニットテストやデバッグに不可欠です。
Pythonのrandomモジュールは安全ですか?
いいえ。randomモジュールはメルセンヌ・ツイスターアルゴリズムを使用しており、決定的で予測可能です。パスワードやトークンなどのセキュリティに敏感なアプリケーションには、暗号学的に安全な乱数ソースを使用するsecretsモジュールを代わりに使用してください。
Pythonでリストをランダムにシャッフルするには?
random.shuffle(my_list)を使って、リストをインプレースでシャッフルします。元のリストが変更され、Noneが返されます。元のリストを変更しないままにする必要がある場合は、先にコピーを作成してください:shuffled = my_list.copy(); random.shuffle(shuffled)。
まとめ
Pythonのrandomモジュールは、一般的なランダム化のあらゆるニーズに対応します:整数にはrandint、浮動小数点数にはuniform、シーケンスからの選択にはchoice/choices/sample、並べ替えにはshuffle、再現性にはseed。重要な違いを覚えておきましょう:choicesは重複を許可(復元抽出)、sampleは許可しません(非復元抽出)。そしてセキュリティには決してrandomを使わないでください -- 代わりにsecretsを使用してください。