LoginSignup
11
2

More than 5 years have passed since last update.

python で重み付きrandom choice

Last updated at Posted at 2016-11-30

numpy 使うと楽。

import numpy as np

d = [("foo", 98), ("bar", 844), ("baz", 1028)]
a, w = zip(*d)
print(a, w)
# -> ('foo', 'bar', 'baz') (98, 844, 1028)

w2 = np.array(w) / sum(w)
v = np.random.choice(a, p=w2)
print(v)
# -> baz


# 確認
from collections import Counter
c = [ np.random.choice(a, p=w2) for i in range(sum(w)) ]
print(Counter(c))
# -> Counter({'baz': 1051, 'bar': 824, 'foo': 95})

だいたい合ってる。

numpy 使わない版

これだけのために numpy 入れるのもなぁ…な場合は bisect 使うといいかも。

import bisect
import itertools
import random

d = [("foo", 98), ("bar", 844), ("baz", 1028)]
a, w = zip(*d)
print(a, w)

ac = list(itertools.accumulate(w))
f = lambda : bisect.bisect(ac, random.random() * ac[-1])
v = a[f()]
print(v)

# 確認
from collections import Counter
c = [ a[f()] for i in range(sum(w)) ]
print(Counter(c))
# -> Counter({'baz': 1010, 'bar': 851, 'foo': 109})

だいたい合ってる。

11
2
0

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
11
2