# Most pythonic way of weighted random selection

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

```-----BEGIN PGP SIGNED MESSAGE-----
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
else:
break_loop = True
else:
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.

Bests,
Manuel
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.7 (Darwin)

iD8DBQFIuWoncZ70OCIgLecRArV4AJ9ynhC/McegMIYTWOOOW4p44t3rWgCbBjvm
1JRHy5kp1qIGLDaCTXXFcSs=
=X6Sv
-----END PGP SIGNATURE-----

```