Python随机选择与“百分比”

3

前言

看起来这可能是几个stackoverflow问题的重复,但我的情况(可能)略有不同。

我的情况

我有一个字典。 是一个 字符串 是一个 整数

我希望Python脚本可以随机选择 N

值表示被选择的可能性大小。 键的值越高,被随机选择的概率就越高。

我的解决方案

因此,使用其他StackOverflow帖子和互联网的力量,我成功地使用了加权随机来解决它。

DICT_VAR= {'best':308281009, 'good':7066325, 'meh':26884, 'bad':71, 'terrible':16, 'never':0}

list_var = []
for i in DICT_VAR.keys():
    list_var.extend([i]*DICT_VAR[i])

print random.sample(list_var, 2) # get 2 random choice I suppose

问题(陷阱)
正如您所注意到的,字典中的值可能非常大(可以无限大),也可能小至0(零是最小值,没有负数)。
运行这段代码(使用稍大的数字)导致我的计算机冻结并无响应,直到我强制重启。
我的问题
我该如何处理这种情况?是否有其他适合我情况的随机选择方法,因为加权随机是当前情况下最糟糕的解决方案。
2个回答

5

在这里,我假设0的值意味着该键永远不应该被选择,在样本中可能会重复使用这些键(在字典中是无关紧要的),我们可以使用第三方模块——numpy。以下是在Python 3.6.4中测试过的代码,但我已经修改了它,所以它应该可以在Python 2.7中运行,但我无法以这种方式进行测试。

DICT_VAR= {'best':308281009, 'good':7066325, 'meh':26884, 'bad':71,
           'terrible':16, 'never':0}

import numpy as np

keys, weights = zip(*DICT_VAR.items())
probs = np.array(weights, dtype=float) / float(sum(weights))
sample_np = np.random.choice(keys, 2, p=probs)
sample = [str(val) for val in sample_np]

然后sample将你的样本作为一组关键字符串列表进行保存。注意,由于与其他权重相比,关键字'best'的权重要大得多,因此你的样本几乎总是['best', 'best']

解释我的代码:先将字典的键(字符串)和值(权重)分别拆分成不同的列表。然后将权重转换为概率--较大的权重给出较大的概率,零权重给出零概率。接着使用numpy的choice函数使用权重来选择一组关键字的样本。结果是一个numpy数组,但你似乎想要一个标准的Python列表,所以最后一行将关键字样本转换为标准列表。

当然,有一种相当短的例程可以用标准Python编写,因此我们可以避免使用numpy。但它可能会更慢。

你的例程之所以慢是因为它构建了一个大列表,每个键都重复了其值给出的次数,然后从中使用均匀概率选择一组样本。对于你的样本数据,这意味着构建一个巨大的列表,比可用的RAM还要大得多,并且需要花费很长时间。Numpy的选择例程可以直接处理非均匀随机分布,而无需构建另一个列表。


是的,你的假设大多是正确的。如果值为0,则不会选择该键。这些密钥是唯一的,但我认为这不会影响你的代码,对吧?是的,只要模块在Windows机器上受支持并且适用于Python 2.7(最好可以使用pip安装),那就没问题了。 - Programer Beginner
我正在运行Python 3.6.4,没有Python 2.7安装的权限。Numpy可以在2.7中运行,但显然有些不同,可能是在numpy中或者是在我的代码中。(我想我已经找到了原因——除法——请尝试我的新代码。)“键可能重复”是指一个给定的键可以在样本中出现多次。它是否在输入字典中唯一是无关紧要的。 - Rory Daulton

1
在Py 3.6中,这是标准库的一部分,使用random.choices()函数:
In []:
import random
random.choices(list(DICT_VAR.keys()), DICT_VAR.values(), k=2)

Out[]:
['best', 'best']

或者稍微更神秘一些:
random.choices(*zip(*DICT_VAR.items()), k=2)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接