Python 3.5中使用random.choices()的替代方法是什么?

4

由于在 Python 3.5 中没有 random.choices() 函数,是否有替代方法?


我已经阅读了文档部分,发现其中的方法只适用于概率是整数的情况下(针对Python 3.5版本)。是否有其他可以使用的方法?https://docs.python.org/3.5/library/random.html - Siddharamesh
1
random.choices 是用 Python 编写的,因此您可以将该方法的代码简单地复制到您的代码库中。 - Mark Dickinson
2个回答

2

按照Mark Dickinson的建议,将代码从Python 3.6复制到中。

from itertools import accumulate as _accumulate, repeat as _repeat
from bisect import bisect as _bisect
import random
def choices(population, weights=None, *, cum_weights=None, k=1):
    """Return a k sized list of population elements chosen with replacement.
    If the relative weights or cumulative weights are not specified,
    the selections are made with equal probability.
    """
    n = len(population)
    if cum_weights is None:
        if weights is None:
            _int = int
            n += 0.0    # convert to float for a small speed improvement
            return [population[_int(random.random() * n)] for i in _repeat(None, k)]
        cum_weights = list(_accumulate(weights))
    elif weights is not None:
        raise TypeError('Cannot specify both weights and cumulative weights')
    if len(cum_weights) != n:
        raise ValueError('The number of weights does not match the population')
    bisect = _bisect
    total = cum_weights[-1] + 0.0   # convert to float
    hi = n - 1
    return [population[bisect(cum_weights, random.random() * total, 0, hi)]
            for i in _repeat(None, k)]

现在你可以安心使用choices函数!

0

我并没有完全爱上Venkatesh Mondi的回答,但它是完全可用的。

import random

def random_choices(population, weights=None, k=1):
    """
    This function achieves the same result. 
    If weights is not provided, it returns a list of k random choices made using random.
    choice with no weighting. If weights is provided, it first normalizes the weights by 
    dividing each weight by the sum of all the weights, and then returns a list of k random 
    choices made using random.choice with the normalized weights.
    """
    if weights is None:
        return [random.choice(population) for _ in range(k)]
    total = sum(weights)
    weights = [weight/total for weight in weights]
    cumulative_weights = [sum(weights[:i+1]) for i in range(len(weights))]
    return [population[cumulative_weights.index(next(x for x in cumulative_weights if x >= random.random()))] for _ in range(k)]
    #note you may also do something like: 
    return population[weights.index(random.choice(weights))]
print(random_choices(population, weights=weights, k=1)[0])

这是一个我已经使用了一段时间的替代方案,我不确定是否有人先写过它或者是我写的。


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