2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

口数を考慮して抽選する

Last updated at Posted at 2018-06-28

複数口応募できます!なキャンペーンをやったら、思いの外抽選で苦戦したので備忘録

検索の仕方が悪いのかもしれませんが、意外と簡単にやる方法が出てこなかったので書きます。
結論としては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]

ちゃんと重み通り抽選されているのが確認できました。

2
2
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?