A weighted version of random.choice

后端 未结 25 2374
闹比i
闹比i 2020-11-21 06:29

I needed to write a weighted version of random.choice (each element in the list has a different probability for being selected). This is what I came up with:



        
25条回答
  •  生来不讨喜
    2020-11-21 06:51

    Crude, but may be sufficient:

    import random
    weighted_choice = lambda s : random.choice(sum(([v]*wt for v,wt in s),[]))
    

    Does it work?

    # define choices and relative weights
    choices = [("WHITE",90), ("RED",8), ("GREEN",2)]
    
    # initialize tally dict
    tally = dict.fromkeys(choices, 0)
    
    # tally up 1000 weighted choices
    for i in xrange(1000):
        tally[weighted_choice(choices)] += 1
    
    print tally.items()
    

    Prints:

    [('WHITE', 904), ('GREEN', 22), ('RED', 74)]
    

    Assumes that all weights are integers. They don't have to add up to 100, I just did that to make the test results easier to interpret. (If weights are floating point numbers, multiply them all by 10 repeatedly until all weights >= 1.)

    weights = [.6, .2, .001, .199]
    while any(w < 1.0 for w in weights):
        weights = [w*10 for w in weights]
    weights = map(int, weights)
    

提交回复
热议问题