我有對象列表「p」,每個對象都有一些數字「a」(例如p [3] .a = 5)。我想從列表中選擇隨機對象,方式是選擇對象的概率與a的值成比例,即選擇a = 5的對象的概率是選擇a = 1的對象的概率的五倍。我怎麼用Python/Pylab/Numpy來做到這一點?Python - 從列表中選擇隨機對象
謝謝!
我有對象列表「p」,每個對象都有一些數字「a」(例如p [3] .a = 5)。我想從列表中選擇隨機對象,方式是選擇對象的概率與a的值成比例,即選擇a = 5的對象的概率是選擇a = 1的對象的概率的五倍。我怎麼用Python/Pylab/Numpy來做到這一點?Python - 從列表中選擇隨機對象
謝謝!
這將適用於整數計數,雖然它不會有效的大計數。
c = collections.Counter({k:k.a for k in stuff})
random.choice(list(c.elements()))
下面是一個更有效的方法。
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
我建議使用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])
你必須建立與斷點列表中只有一次。然後,只要你喜歡,你可以使用它相當快的對分算法。
最後一個循環只是爲了演示結果。
編輯:另一種方法得到斷點(我不喜歡for循環):
values = [value.a for value in data]
breakpoints = [sum(values[:pos+1]) for pos in xrange(len(values))]
而不'Counter'等效方法:'random.choice([X爲P X [因爲我在範圍內(xa)])' – agf