代码之家  ›  专栏  ›  技术社区  ›  Simon

如何从字典中获取随机对象,按值[重复]加权

  •  0
  • Simon  · 技术社区  · 6 年前

    我有一本大字典。键是对象,值是给定对象在我的数据中出现的频率。

    我想从字典中随机选择一个对象,但要将选择权放在对应值较高的对象上。

    到目前为止,我已经能够通过向列表中添加x个对象来实现这一点,其中x是字典中相应的值。然后我打电话 random.choice() 在这个名单上。像这样:

    import random
    
    myDict = { 'foo' : 10,
               'boo' : 5,
               'moo' : 3,
               'roo' : 2,
               'goo' : 1,
               'oo' : 0}
    
    selection = []
    for obj in myDict.keys():
        for n in range(myDict[obj]):
            selection.append(obj)
    

    random.choice() 上榜10000次并保存了结果。下面是我得到的四个结果。

    {'foo': 4841, 'boo': 2397, 'moo': 1391, 'roo': 907, 'goo': 464, 'oo': 0}
    {'foo': 4771, 'boo': 2410, 'moo': 1435, 'roo': 917, 'goo': 467, 'oo': 0}
    {'foo': 4815, 'boo': 2340, 'moo': 1431, 'roo': 953, 'goo': 461, 'oo': 0}
    {'foo': 4718, 'boo': 2443, 'moo': 1404, 'roo': 947, 'goo': 488, 'oo': 0}
    

    如您所见,分布符合字典中描述的频率。

    我的问题是,在我的生产代码中,我有数千个字典,每个字典包含数千个对象。这些词典长度可变。我现在的方法效率很低,速度也很慢。有更好的办法吗?我不介意使用不同的结构来存储传入的数据。

    1 回复  |  直到 6 年前
        1
  •  1
  •   Randy    6 年前

    numpy 提供一个适用于您的问题的可选概率参数:

    In [14]: s = sum(myDict.values())
    
    In [15]: d2 = {k: v/float(s) for k, v in myDict.items()}
    
    In [16]: res = np.random.choice(list(d2.keys()), 10000, p=list(d2.values()))
    
    In [17]: from collections import Counter
    
    In [18]: Counter(res)
    Out[18]: Counter({'foo': 4723, 'moo': 1426, 'boo': 2411, 'roo': 945, 'goo': 495})