我有一张4 * 10 ^ 8(大致)记录的表格,我希望得到一个4 * 10 ^ 6(完全)的样本。
但我获取样本的方式有点特别:
我想到了解决这个问题的方法:
A(num int)
,表A
的每个记录中只有一个数字,它是从1到n的随机整数(n是我原始表的大小,大约是4 * 10 ^如上所述8)。A
作为资源文件加载到每个地图,如果现在决定的记录的序号在表A
中,则输出此记录,否则丢弃它。我认为我的方法不太好,因为如果我想从原始表中采样更多记录,表A
将变得非常大并且无法作为资源文件加载。
那么,任何人都可以给出一个优雅的算法吗?
答案 0 :(得分:1)
我不确定"优雅"意思是,但也许你对类似于油藏采样的东西感兴趣。设k为样本的大小,并用空值初始化k元素数组。我们抽样的元素一个接一个地到达。当第j个(从1开始计数)元素到达时,我们遍历数组,并且对于每个单元,用当前元素以1 / j的概率独立地替换它的内容。
天真地,运行时间非常糟糕 - 从n中采样k元素,替换成本为O(k n)。但是,对数组的写入次数是期望的O(k log n),因为流中的后续元素很少导致写入。这是一个基于exponential distribution的有效方法(警告:前面轻度测试的Python)。运行时间为O(n + k log n)。
import math
import random
def sample_from(population, k):
for i, x in enumerate(population):
if i == 0:
sample = [x] * k
else:
t = float(k) * math.log(1.0 - 1.0 / float(i + 1))
while True:
t -= math.log(1.0 - random.random())
if t >= 0.0:
break
sample[random.randrange(k)] = x
return sample