Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Select random item with weight

Tags:

python

random

I have a list of approx. 10000 items. The current situation is that every item has an associated weight (priority or importance). Now the smallest weight is -100 (negative and zero values can be removed) and the highest weight is 1500. Weight is determined by intuition by people (how somebody thinks the item is important to community). Because it's not easy to determine the most important item, I'd like to use some random factor, so that items with lower weight will have less chance to be chosen and their weight will be adjusted in the future (some mix of common sense and randomness).

Do you know how to code a function getItem?

def getItem(dict):
  # this function should return random item from 
  # the dictionary of item-weight pairs (or list of tuples)
  # Normally I would return only random item from the dictionary,
  # but now I'd like to have this: The item with weight 1500 should
  # have much more chance to be returned than the item with weight 10.
  # What's my idea is to sum up the weights of all items and then compute
  # some ratios. But maybe you have better idea.
  return randomItem

Thank you

like image 915
xralf Avatar asked Feb 13 '12 11:02

xralf


2 Answers

Have a look at this, i think it's what you need with some nice comparision between different methods Weighted random generation in Python

The simplest approach suggested is:

import random

def weighted_choice(weights):
    totals = []
    running_total = 0

    for w in weights:
        running_total += w
        totals.append(running_total)

    rnd = random.random() * running_total
    for i, total in enumerate(totals):
        if rnd < total:
            return i

You can find more details and possible improvements as well as some different approaches in the link above.

like image 197
Bogdan Avatar answered Nov 15 '22 18:11

Bogdan


Python 3.6 introduced random.choices()

def get_item(items, items_weights):
    return random.choices(items, weights=items_weights)[0]
like image 42
m.elahi Avatar answered Nov 15 '22 19:11

m.elahi