Returning a value at random based on a probability

2019-09-14 19:22发布

Possible Duplicate:
A weighted version of random.choice

Let's say for simplicity a function takes in 4 inputs: 2 names and their respective 'bias/weights', how can I write a function such that it returns either a or b at random but still considers those weights into the random outcome.

a = 'x'
b = 'y'
p_a = 10
p_b = 90

def myRand(a, p_a, b, p_b):
    return 'x' 10% of the time, 'y' 90% of time

What I've done so far

import random

def myRand(a, p_a, b, p_b):
    probs = [a]*p_a + [b]*p_b
    return random.choice(probs)

Can someone point why this is an incorrect or not the best answer? My justification is that I'm assuming every element has the same probability of being picked so the outcome should still favor 10:90. Or maybe we can shuffle the array before using random.choice() ?

Is there a better way to do this? Maybe I'm missing something obvious here or is this correct?

Thanks

3条回答
ゆ 、 Hurt°
2楼-- · 2019-09-14 19:25

This would accomplish what you're trying to do:

#assumes p_a and p_b are both positive numbers that sum to 100
def myRand(a, p_a, b, p_b):
   return a if random.uniform(0,100) < p_a else b 

Note that p_b becomes unnecessary in your special case of having only 2 weights, since p_b == 100-p_a.

查看更多
何必那么认真
3楼-- · 2019-09-14 19:27

a = 'x';b = 'y';p_a = 10;p_b = 90

ratio = p_a+pb = 100

generate a random number between 0 and 100 and if the number is less than 10 use a=>x else use b=>y

查看更多
冷血范
4楼-- · 2019-09-14 19:41

I've modified the function to accept an arbitrary number of inputs and weighted probabilities so if later on you decide you want to use more than two inputs, you can.

import random

def myRand(i, w):
    r = random.uniform(0, sum(w))

    # loop through a list of inputs and max cutoff values, returning
    # the first value for which the random num r is less than the cutoff value
    for n,v in map(None, i,[sum(w[:x+1]) for x in range(len(w))]):
        if r < v:
            return n

Example usage:

inputs = ['e', 'f', 'g', 'h']
weights = [10, 30, 50, 10]

print myRand(inputs, weights)
查看更多
登录 后发表回答