Most pythonic way of weighted random selection

Manuel Ebert maebert at
Sat Aug 30 17:41:27 CEST 2008

Hash: SHA1

Dear list,

who's got aesthetic advice for the following problem? I've got some  
joint probabilities of two distinct events Pr(X=x, Y=y), stored in a  
list of lists of floats, where every row represents a possible  
outcome of X and every float in a row a possible outcome of Y (which  
I will now call my matrix, altough I can't use numpy or numeric for  
this), so e.g. m = [[0.2, 0.4, 0.05], [0.1, 0.05, 0.2]]. All lists in  
the list are equally long and the values of the flattened list add up  
to 1.0, i.e. sum([sum(row) for row in m]) == 1. In practice, this  
'matrix' is about 20x40, i.e. a list with 20 lists á 40 floats each.

Now the task is to select one outcome for X and Y based on the joint  
probabilites, and afterwards check that the outcomes fullfill certain  
criteria. If it doesn't fulfill some criteria a new pair of outcomes  
has to be selected, for other criteria it will still be selected with  
a certain probability. My approach was to choose a random number, and  
then walk through the list adding the values together until the  
accumulated sum is greater than my random threshold:

import random
r = random.random()
s = 0.0
p = 0.2 # probability of selecting outcome if it doesn't fulfill  
criterion 2
break_loop = False
while not break_loop:
	for row_index in range(len(m)):
		for col_index in range(len(row)):
			s += m[row_index][col_index]
			if s >= r:
				if not fulfills_criterion_a(row_index, col_index):
					break_loop = True
				elif not fulfills_criterion_b(row_index, col_index):
					if random.random() <= p:
						return row_index, col_index
						break_loop = True
					return row_index, col_index
			if break_loop: break
		if break_loop: break
	break_loop = False

Now that looks plain ugly, and I wonder whether you might find a  
slightly more elegant way of doing it without using numpy and the like.

Version: GnuPG v1.4.7 (Darwin)


More information about the Python-list mailing list