gpt4 book ai didi

Python:使用频率数据对总体进行下采样

转载 作者:太空宇宙 更新时间:2023-11-03 18:56:50 25 4
gpt4 key购买 nike

给定代表总体中元素频率的数据系列,对其进行下采样的最简单方法是什么?

以下人口:pop = ['a', 'b', 'a', 'c', 'c', 'd', 'c', 'a', 'a', ' b', 'a']

可以总结为:freq = {'a': 5, 'c': 3, 'b': 2, 'd': 1}

使用简单:from collections import Counter;计数器(弹出)

要将该总体随机抽样到 5 个个体,我可以这样做:

>>> from random import sample
>>> from collections import Counter
>>> pop = ['a', 'b', 'a', 'c', 'c', 'd', 'c', 'a', 'a', 'b', 'a']
>>> smaller_pop = sample(pop, 5)
>>> smaller_freq = Counter(smaller_pop)
>>> print smaller_freq
Counter({'a': 3, 'c': 1, 'b': 1})

但我正在寻找一种直接从 freq 信息执行此操作的方法,而无需构建 pop 列表。您会同意没有必要进行这样的操作:

>>> from random import sample
>>> from collections import Counter
>>> flatten = lambda x: [item for sublist in x for item in sublist]
>>> freq = {'a': 5, 'c': 3, 'b': 2, 'd': 1}
>>> pop = flatten([[k]*v for k,v in freq.items()])
>>> smaller_pop = sample(pop, 5)
>>> smaller_freq = Counter(smaller_pop)
>>> print smaller_freq
Counter({'a': 2, 'c': 2, 'd': 1})

出于内存考虑和速度要求,我希望避免将 pop 列表放入内存中。这当然可以使用某种类型的加权随机生成器来完成。

最佳答案

这是一个降低频率采样的基本算法:

import random
import bisect
import collections

def downsample(freq, n):
cumsums = []
total = 0
choices, weights = zip(*freq.items())
for weight in weights:
total += weight
cumsums.append(total)
assert 0 <= n <= total
result = collections.Counter()
for _ in range(n):
rnd = random.uniform(0, total)
i = bisect.bisect(cumsums, rnd)
result[choices[i]] += 1
cumsums = [c if idx<i else c-1 for idx, c in enumerate(cumsums)]
total -= 1
return result

freq = {'a': 5, 'c': 3, 'b': 2, 'd': 1}
print(downsample(freq, 5))

打印结果如下

Counter({'c': 2, 'a': 1, 'b': 1, 'd': 1})

关于Python:使用频率数据对总体进行下采样,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17088636/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com