1

I have list of objects "p", every object has some number "a" (for example p[3].a = 5) . I want to choose random object from the list, in the way that the probability of choosing an object is proportional to its value of a, i.e. the probability of choosing object with a=5 is five times the probability of choosing object with a=1. How can I do it with Python/Pylab/Numpy?

thank you!

0

3 Answers 3

2

This will work for integer counts, though it won't be efficient for large counts.

c = collections.Counter({k:k.a for k in stuff}) random.choice(list(c.elements())) 
Sign up to request clarification or add additional context in comments.

1 Comment

The equivalent method without Counter: random.choice([x for x in p for i in range(x.a)])
2

Here's a more efficient way to do it.

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 

Comments

0

I'd suggest using 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]) 

You have to build the list with the breakpoints just once. Then you can use it with the pretty fast bisect algorithm as long as you like.

The last loop is just to demonstrate the result.

Edit: An alternative approach to get the breakpoints (I didn't like the for-loop):

values = [value.a for value in data] breakpoints = [sum(values[:pos+1]) for pos in xrange(len(values))] 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.