シミュレーションなどをしたいときに、
適当にデータを生成したり、
既にあるデータを一旦へらすためにサンプリングしたい場合があります。
特に、自分で現実を表現した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 (以下略)