我有对象列表“p”,每个对象都有一些数字“a”(例如 p[3].a = 5)。我想从列表中选择随机对象,选择对象的概率与其a的值成正比,即选择a=5的对象的概率是选择a=1的对象的概率的五倍. 我怎样才能用 Python/Pylab/Numpy 做到这一点?
谢谢你!
我有对象列表“p”,每个对象都有一些数字“a”(例如 p[3].a = 5)。我想从列表中选择随机对象,选择对象的概率与其a的值成正比,即选择a=5的对象的概率是选择a=1的对象的概率的五倍. 我怎样才能用 Python/Pylab/Numpy 做到这一点?
谢谢你!
这是一种更有效的方法。
import random
def weighted_choice(items):
# check if no items exist
if not items:
return None
# compute total of all weights
total = sum(item.weight for item in items)
# select a random point within the total
selection = random.randint(0, total - 1)
# find the corresponding item
count = 0
for item in items:
count += item.weight
if selection < count:
return item
这适用于整数计数,尽管它对于大计数无效。
c = collections.Counter({k:k.a for k in stuff})
random.choice(list(c.elements()))
我建议使用bisect
from bisect import bisect
class Element(object):
def __init__(self, value):
self.a = value
def __repr__(self):
return 'Element({})'.format(self.a)
data = [Element(3), Element(5), Element(7), Element(1)]
last = 0
breakpoints = []
for element in data:
breakpoints.append(last + element.a)
last += element.a
print(breakpoints)
for random_value in xrange(last):
pos = bisect(breakpoints, random_value)
print(random_value, data[pos])
您只需使用断点构建列表一次。然后,只要您愿意,您就可以将它与非常快速的 bisect 算法一起使用。
最后一个循环只是为了演示结果。
编辑:获取断点的另一种方法(我不喜欢 for 循环):
values = [value.a for value in data]
breakpoints = [sum(values[:pos+1]) for pos in xrange(len(values))]