【计算引擎】水塘抽样算法

spark中的分区器有三种:
1.HashPartitioner分区可能HashPartitioner导致每个分区中数据量的不均匀。
2.RangePartitioner分区尽量保证每个分区中数据量的均匀,将一定范围内的数映射到某一个分区内。分区与分区之间数据是有序的,但分区内的元素是不能保证顺序的。(这里其实就用到了水塘抽样算法)
3.自定义

那水塘抽样算法是什么呢?能解决什么类型的问题呢?

问题描述:
给定一个数据流,数据流长度N很大,且N直到处理完所有数据之前都不可知,如何在只遍历一遍数据(O(N))的情况下,能够随机选取出这组数据的k个概率相等的均匀抽样。
要求:

  1. 仅扫描数据一次
  2. 空间复杂度为O(N),空间复杂度与整个数据量无关,只与抽样大小有关。
  3. 扫描到数据的前n个数据时(n>k),保存当前已扫描数据的k个均匀抽样。

根据要求,首先体积很大内存一次装不下,不能直接不能直接取N内的k个随机数,因为N的长度是未知的。此外也不能采用不能先遍历一遍,然后分块存储数据,再随机选取。最后要求是数据选取绝对随机的保证。

可以采用水塘抽样算法:

  1. 如果接受的数据量小于k,则依次放入采样数组中
  2. 当接收到第i个数据,i大于等于k时,在[0,i]的范围内取一个随机数d 如果d落在了[0,k-1]的范围内,则取接收到的第i个数据替换采样数组中下标等于d位置上的值。
  3. 重复步骤2
// @param:input 模拟的原始数组
// @param:k 采样的个数
// return:返回采样的数据

import random
def sample(input, k):
    res = []
    for i in range(len(input)):
        if i<k:
            res.append(input[i])//先取,前k个数字放在数组里面
        else:
        //如果i>k,在0和i之间,取一个随机数字,如果这个随机数字小于k,就替换数组,否则就继续遍历,直到结束
            rand = random.randint(0, i)
            if rand < k:
                res[rand] = input[i]
    return res

这种算法的能保证概率相等的前提就是: 当数据总量加1的时候,都会在当前总量的范围内,进行生成随机数,这样就能保证范围内的所有的数字出现概率都是相等的,然后根据概率均等随机数字来判断,是否落在了我们采样数组的边界中,如果落到了就替换原来数组中相同的位置的值,如果没有落到,就继续遍历选取,直到所有的数据处理完毕。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

孟知之

如果能帮助到你们,可否点个赞?

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值