Взвешенная случайная выборка в питоне
Я ищу разумное определение функцииweighted_sample
это не возвращает только один случайный индекс для списка заданных весов (который был бы что-то вроде
def weighted_choice(weights, random=random):
""" Given a list of weights [w_0, w_1, ..., w_n-1],
return an index i in range(n) with probability proportional to w_i. """
rnd = random.random() * sum(weights)
for i, w in enumerate(weights):
if w<0:
raise ValueError("Negative weight encountered.")
rnd -= w
if rnd < 0:
return i
raise ValueError("Sum of weights is not positive")
дать категорическое распределение с постоянными весами), но случайная выборкаk
из тех,без замены, как толькоrandom.sample
ведет себя по сравнению сrandom.choice
.
Как толькоweighted_choice
можно записать как
lambda weights: random.choice([val for val, cnt in enumerate(weights)
for i in range(cnt)])
weighted_sample
может быть написано как
lambda weights, k: random.sample([val for val, cnt in enumerate(weights)
for i in range(cnt)], k)
но я хотел бы получить решение, которое не требует от меня распутывания весов в (возможно, огромный) список.
Редактировать: Если есть какие-либо хорошие алгоритмы, которые возвращают мне гистограмму / список частот (в том же формате, что и аргументweights
) вместо последовательности индексов это также было бы очень полезно.