あれもPython,これもPython

Pythonメモ※本サイトはアフィリエイトを利用しています

Pythonだけで乱数を扱いシミュレーションをしたい(randomを用いる)

シミュレーションなどをしたいときに、
適当にデータを生成したり、
既にあるデータを一旦へらすためにサンプリングしたい場合があります。

特に、自分で現実を表現したobjectをつくり、
乱数でデータを与えたい場合に、numpyやscipyをわざわざ使わず、
randomを用いて、Python単体でも完結することができます。

よく使いそうなもの

メソッド 取得できるもの
choice 集団から一つデータを取得
randint 対象範囲の整数を取得
random 0~1の間の少数を取得
gauss 与えたパラメータのガウス分布から値を取得

状況設定

かなり適当な状況設定になってしまいますが、
会社の仕事にかかる時間をシミュレーションしたいとします。

仕事が増えた時と、人が増えた時に、
総仕事時間と一人当たり仕事時間がどう変化するかを見ることにします

このとき、仕事にかかる時間は、する人に依存させたく、
人のこなす力と誰が仕事をするかは、ひとまずランダムだとします。

コード

import random
import statistics

class Work:
  """
  仕事オブジェクト
  人の実力によってかかる時間の分布が変わる
  """
  def __init__(self,worker_id,mu,sigma):
    self.worker_id = worker_id
    #ガウス分布を発生させる
    self.time = random.gauss(mu,sigma)

class Employee:
  """
  従業員オブジェクト
  仕事をこなす平均時間とばらつきはランダムによって変わる
  """
  def __init__(self,id):
    self.id = id
    #平均:1~10までの整数がランダムに選ばれる
    self.avg_work_time = random.randint(1,10)
    #ばらつき:0~1のランダムな数
    self.sigma_work_time = random.random()


#シミュレーション:仕事数と従業員数を徐々に変える
for work_num in range(10,111)[0::25]:
  for employee_num in range(1,10):
    #上記パラメータごとに1000回ずつ
    total_work_times = []
    work_time_per_e = []
    for num in range(1000):
        employees = [Employee(i) for i in range(employee_num)]
        
        works = []
        for i in range(work_num):
          #仕事は従業員にランダムに割り当てられる
          e = random.choice(employees)
          w = Work(e.id,e.avg_work_time,e.sigma_work_time)
          works.append(w)
        
        total_work_time = sum([round(w.time) for w in works])
        
        #結果のリストに格納
        #前ワーク時間
        total_work_times.append(total_work_time)
        #一人当たりワーク時間
        work_time_per_e.append(total_work_time/float(employee_num))
    res = "work_num:{0},employee_num:{1},total_work_time:{2},e_work_time:{3}"
    print(
        res.format(
            str(work_num),
            str(employee_num),
            str(statistics.mean(total_work_times)),
            str(statistics.mean(work_time_per_e))
            
        )
    )
work_num:10,employee_num:1,total_work_time:55.146,e_work_time:55.146
work_num:10,employee_num:2,total_work_time:56.61,e_work_time:28.305
work_num:10,employee_num:3,total_work_time:54.653,e_work_time:18.217666666666666
work_num:10,employee_num:4,total_work_time:54.958,e_work_time:13.7395
work_num:10,employee_num:5,total_work_time:55.665,e_work_time:11.133
(以下略)