複数口応募できます!なキャンペーンをやったら、思いの外抽選で苦戦したので備忘録
検索の仕方が悪いのかもしれませんが、意外と簡単にやる方法が出てこなかったので書きます。
結論としてはnumpyのrandomchoiceでいけました。
まず抽選対象のリストを作ります。
import numpy as np
lottery=[[i,np.random.randint(1,20)] for i in range(20)]
print(lottery)
[[0, 13], [1, 3], [2, 15], [3, 3], [4, 7], [5, 2], [6, 2], [7, 9], [8, 11], [9, 16],
[10, 17], [11, 10], [12, 13], [13, 18], [14, 18], [15, 3], [16, 4], [17, 2], [18, 12], [19, 9]]
通常は会員番号と口数の組み合わせが人数分揃っているはずです。
ここでは会員番号の代わりに連番をふり、口数はランダムで出力しました。
抽選するためにデータを整形します。
lottery2=np.array(lottery).transpose()]
print(lottery2)
[[ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19],
[13, 3, 15, 3, 7, 2, 2, 9, 11, 16, 17, 10, 13, 18, 18, 3, 4, 2, 12, 9]]
とりあえずリストを反転させたいので、np.arrayを使って軸を入れ替えます。
重みの作成
抽選の際は口数を重みとして読み込ませる必要があります。
重みの合計が1にならなければ行けないという制約があるようなので、
weight=np.dot(lottery2[1],1/np.sum(lottery2[1]))
print(weight)
[ 0.06951872 0.01604278 0.0802139 0.01604278 0.03743316 0.01069519
0.01069519 0.04812834 0.05882353 0.0855615 0.09090909 0.05347594
0.06951872 0.09625668 0.09625668 0.01604278 0.02139037 0.01069519
0.06417112 0.04812834]
抽選する
準備ができたので早速抽選してみます。
今回は20人の中から3名抽選します。
winner=np.random.choice(lottery2[0],3,replace=False, p=weight)
print(winner)
[13 7 19]
無事3名が抽出されました。
ちなみに複数当選可にする場合はreplaceをTrueにします。
抽選結果を固定する
random choice なので実行するたびに結果が変わります。
ただ、公正性を確保するために抽選プロセスを再現可能な状態にします。
np.random.seed(20)
winner=np.random.choice(lottery2[0],3,replace=False, p=weight)
print(winner)
方法はシンプルでrandom choiceする前にrandom.seedを挿入するだけです。
random.seedの引数に任意の数字を入れてやると、同じデータを読み込んでいる限り、何回やり直しても同じ数字が出力されます。(私はデータ数が20なので20みたいに決めました。)
検証
ちゃんと重み通りに抽選されているか10,000回抽選してみて確認します。
counter=np.zeros(20)
for i in range(10000):
winner=np.random.choice(lottery2[0],3,replace=False, p=weight)
for i in winner:
counter[i]+=1
p=counter/30000
print(p)
[ 0.07096667 0.0172 0.07656667 0.0171 0.03916667 0.01163333
0.01126667 0.04936667 0.05983333 0.08226667 0.08793333 0.0536
0.06886667 0.095 0.09276667 0.01783333 0.0224 0.01273333
0.0631 0.0504 ]
[ 0.06951872 0.01604278 0.0802139 0.01604278 0.03743316 0.01069519
0.01069519 0.04812834 0.05882353 0.0855615 0.09090909 0.05347594
0.06951872 0.09625668 0.09625668 0.01604278 0.02139037 0.01069519
0.06417112 0.04812834]
ちゃんと重み通り抽選されているのが確認できました。