1

オブジェクトのリスト「p」があり、すべてのオブジェクトにはいくつかの番号「a」があります(たとえば、p[3].a = 5)。オブジェクトを選択する確率が a の値に比例するように、リストからランダムなオブジェクトを選択したい。つまり、a=5 のオブジェクトを選択する確率は、a=1 のオブジェクトを選択する確率の 5 倍である. Python/Pylab/Numpyでどうすればいいですか?

ありがとう!

4

3 に答える 3

2

これは整数カウントでは機能しますが、大きなカウントでは効率的ではありません。

c = collections.Counter({k:k.a for k in stuff})
random.choice(list(c.elements()))
于 2012-11-12T15:31:33.487 に答える
2

より効率的な方法を次に示します。

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
于 2012-11-12T15:42:00.170 に答える
0

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])

ブレークポイントを含むリストを 1 回だけ作成する必要があります。その後、必要に応じて、非常に高速な bisect アルゴリズムで使用できます。

最後のループは、結果を示すためのものです。

編集: ブレークポイントを取得する別の方法 (for ループは好きではありませんでした):

values = [value.a for value in data]
breakpoints = [sum(values[:pos+1]) for pos in xrange(len(values))]
于 2012-11-12T15:50:45.293 に答える