ゆるふわめも

東京か京都にいます。

pythonで乱数を生成・特定の分布から乱数を生成する

ドキュメント

9.6. random — Generate pseudo-random numbers — Python 3.6.2 documentation

Random sampling (numpy.random) — NumPy v1.12 Manual

を見ればほとんど解決できます。

必要なライブラリをインポート

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.patches as patches

n_samples = 10000

""" グラフの模様を取得 """
def get_patterns(k):
    patterns = ['-', '+', 'x', 'o', 'O', '.', '*'] 
    return patterns[k%len(patterns)]

分布から乱数を生成

一様分布

np.random.rand

data = np.random.rand(n_samples,1)
plt.figure(figsize=(8, 3))
plt.hist(data, bins=50)
plt.grid()

f:id:misos:20170802201039p:plain

random.random

import random
data = [random.random() for _ in range(n_samples)]
plt.figure(figsize=(8, 3))
plt.hist(data, bins=50)
plt.grid()

f:id:misos:20170802201052p:plain

ガンマ分布

plt.figure(figsize=(8, 3))

for i in range(10):
    alpha, beta = i*1+1, 0.5
    labelname = str((alpha, beta))
    data = [random.gammavariate(alpha, beta) for _ in range(n_samples)]
    plt.hist(data, bins=50, label=labelname, alpha=.8, hatch=get_patterns(i))

plt.grid(True)
plt.legend(title="(alpha, beta)", bbox_to_anchor=(1.2,1.02),)

f:id:misos:20170802201133p:plain

ガウス分布

plt.figure(figsize=(8, 3))

for i in range(10):
    mu, sigma = 0, (10-i)+1
    labelname = str((mu, sigma))
    data = [random.gauss(mu, sigma) for _ in range(n_samples)]
    plt.hist(data, bins=50, label=labelname, alpha=.8, hatch=get_patterns(i))

plt.grid(True)
plt.legend(title="(mu, sigma)", bbox_to_anchor=(1.2,1.02),)

f:id:misos:20170802201212p:plain

ワイブル分布

plt.figure(figsize=(8, 3))

for i in range(10):
    alpha, beta = 0.5, i*0.1+1
    labelname = str((alpha, beta))
    data = [random.weibullvariate(alpha, beta) for _ in range(n_samples)]
    plt.hist(data, bins=50, label=labelname, alpha=.8, hatch=get_patterns(i))

plt.grid(True)
plt.legend(title="(alpha, beta)", bbox_to_anchor=(1.2,1.02),)

f:id:misos:20170802201337p:plain

混合ガウス分布

n_gaussians = 10

weight = [ 1.0*np.random.randint(1,100) for _ in range(n_gaussians)]
weight = [ w/np.sum(weight) for w in weight]
xys = []
 
plt.figure(figsize=(10, 10))
for w in weight:
    mean = [np.random.randint(0, 20), np.random.randint(2,20)]
    
    c1, c2 = np.random.randint(1,20), np.random.randint(1,20)
    cov = [[c1, 0], [0, c2]]
    labelname = str(mean)+" "+str(cov)

    x, y = np.random.multivariate_normal(mean, cov, int(w*n_samples)).T
    xys += [(x, y)]
    plt.scatter(x, y, marker=".", label=labelname, alpha=.5)

plt.grid(True)
plt.xlim(-5, 30)
plt.ylim(-5, 30)
plt.legend(title="(mean / covariance)", bbox_to_anchor=(1.1,1.02),)

f:id:misos:20170807103906p:plain

カーネル密度推定した分布のプロット

kdeplotを使います。

import seaborn as sns

sns.set(style="dark")
rs = np.random.RandomState(50)
plt.figure(figsize=(10, 10))
plt.grid(True)
plt.xlim(-5, 30)
plt.ylim(-5, 30)

for (x, y) in xys:
    ax = sns.kdeplot(x, y, n_levels=30, cmap="Purples_d")

f:id:misos:20170807103918p:plain

アイテムを選択

アイテムごとの重みに基づいて選択

アイテムの集合 [1, 2, 3, 4, 5] からそれぞれの重み [.1, .1, .2, .2, .3] に基づいてアイテムを選択します。 ヒストグラムから重みのあるアイテムが選ばれる回数が多くなっている

from numpy.random import choice

items = [1, 2, 3, 4, 5]
number_of_items_to_pick = 1
distribution = np.array([.1, .1, .2, .2, .3])
distribution /= distribution.sum()
pickup = choice(items, n_samples, p=distribution)
plt.hist(pickup)

アイテムをランダムに選択

random.choice(items)を用います。

rand_items = random.sample(items, 3)
rand_items
['b', 'a', 'e']