算法&Map约简实现中的一种特殊样本方法

icomxhvb  于 2021-05-30  发布在  Hadoop
关注(0)|答案(1)|浏览(329)

我有一个410^8(大致)记录的表,我想得到一个410^6(准确)的样本。
但我获取样本的方法有些特别:
我从410^8个记录中随机选择1个记录(每个记录被选择的概率相同)。
重复步骤1 4
10^6次(无论一条记录是否被多次选中)。
我想出了一个方法来解决这个问题:
生成表 A(num int) ,并且表的每条记录中只有一个数字 A 它是从1到n的随机整数(n是我原来表格的大小,大约是4*10^8,如上所述)。
负荷表 A 作为每个Map的资源文件,如果现在决定的记录的序号在表中 A ,则输出此记录,否则将其丢弃。
我认为我的方法不太好,因为如果我想从原始表中抽取更多的记录,表 A 将变得非常大,无法作为资源文件加载。
那么,有谁能给出一个优雅的算法吗?

xtupzzrd

xtupzzrd1#

我不知道“优雅”是什么意思,但也许你对类似于水库取样的东西感兴趣。设k为样本的大小,并用null初始化k元素数组。我们取样的元素一个接一个地到达。当第j个(从1开始计数)元素到达时,我们遍历数组,对于每个单元格,用概率1/j独立地用当前元素替换其内容。
天真地说,运行时间相当糟糕——从n中抽取k个元素,替换成本为o(kn)。但是,写入数组的次数是预期的o(k logn),因为流中后面的元素很少导致写入。下面是一个基于指数分布的有效方法(警告:前面的python测试不太好)。运行时间为o(n+k logn)。

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

相关问题