A weighted version of random.choice

后端 未结 25 1933
闹比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 07:03

    I looked the pointed other thread and came up with this variation in my coding style, this returns the index of choice for purpose of tallying, but it is simple to return the string ( commented return alternative):

    import random
    import bisect
    
    try:
        range = xrange
    except:
        pass
    
    def weighted_choice(choices):
        total, cumulative = 0, []
        for c,w in choices:
            total += w
            cumulative.append((total, c))
        r = random.uniform(0, total)
        # return index
        return bisect.bisect(cumulative, (r,))
        # return item string
        #return choices[bisect.bisect(cumulative, (r,))][0]
    
    # define choices and relative weights
    choices = [("WHITE",90), ("RED",8), ("GREEN",2)]
    
    tally = [0 for item in choices]
    
    n = 100000
    # tally up n weighted choices
    for i in range(n):
        tally[weighted_choice(choices)] += 1
    
    print([t/sum(tally)*100 for t in tally])
    

提交回复
热议问题