对于我正在研究的应用程序,我需要从一个非常大的数据集中采集一小组值,从大约60万亿(并且正在增长)中获取几百个数量级。
通常我使用查看均匀随机数r(0..1)是否小于S / T的技术,其中S是我仍然需要的样本项数,T是项中的项目数。设置我还没有考虑过。
然而,有了这些新数据,我没有时间为每个值滚动模具;有太多了。相反,我想生成随机数量的条目以“跳过”,在下一个位置选择值,然后重复。这样我就可以滚动模具并访问列表S次。 (S是我想要的样本的大小。)
我希望有一种直接的方法可以做到这一点,并按照S / T测试的方式创建一个无偏见的样本。
说实话,大致不偏不倚就行。
这与这个人的问题有关(或多或少都是后续的):
https://math.stackexchange.com/questions/350041/simple-random-sample-without-replacement
答案 0 :(得分:2)
这个怎么样:
...假设您收集样品的顺序无关紧要
答案 1 :(得分:1)
所以我考虑了一下,并从 http://math.stackexchange.com
获得了一些帮助归结为:
x = 1 - (1 - r)**(1 / n)
即, n 次幂的分布为1减去(1-r)。然后求解 x 。很简单。
如果我生成一个统一的随机数并将其插入 r ,则其分布与 min({r_1 ... r_n})相同 - 与最低项目相同的方式。瞧!我只是模拟选择第一项,好像我随机选择了所有 n 。
所以我跳过列表中的那些项目,选择那个,然后......
重复直到 n 为0
这样,如果我有一个大型数据库(如Mongo),我可以跳过,find_one,skip,find_one等等。直到我拥有了我需要的所有项目。
我遇到的唯一问题是我的实现偏好列表中的第一个和最后一个元素。但我可以忍受。
在Python 2.7中,我的实现如下:
def skip(n):
"""
Produce a random number with the same distribution as
min({r_0, ... r_n}) to see where the next smallest one is
"""
r = numpy.random.uniform()
return 1.0 - (1.0 - r) ** (1.0 / n)
def sample(T, n):
"""
Take n items from a list of size T
"""
t = T
i = 0
while t > 0 and n > 0:
s = skip(n) * (t - n + 1)
i += s
yield int(i) % T
i += 1
t -= s + 1
n -= 1
if __name__ == '__main__':
t = [0] * 100
for c in xrange(10000):
for i in sample(len(t), 10):
t[i] += 1 # this is where we would read value i
pprint.pprint(t)