海量数据随机选取
问题1:在不知道文件总行数的情况下,如何从文件中随机的抽取一行,并且每行被抽中的概率相等?
问题2:在不知道文件总行数的情况下,如何从文件中随机的抽取 k 行,并且每行被抽中的概率相等?
问题一:抽取一行
在知道文件行数的情况下,直接用 rand 函数就可以
不知道文件行数的时候,我们需要一个概念来使得对每一行取出的概率相等,也即随机。这个概念即蓄水池抽样
解决方案:
- 直接选取第一行作为我们的最后选择:choice
- 1/2 的概率,将choice换成第二行
- 1/3 的概率,将choice换成第三行
- 。。。
- 1/i 的概率,将choice换成第 i 行
- 。。。
- 1/n 的概率,将choice换成第 n 行
为什么这样可以呢,是有数学方面严格证明的
证明如下:
其实知道每行被选取的概率的公式之后,自己就可以推导
问题二:抽取 K 行(问题一的扩展)
当理解了问题一,其实问题二就很好理解,可以将 k 行数据看做一个整体
解题思路:
- 读取第 i 行,以 k/i 概率决定是否要把它换入蓄水池,
- 如果要换入,换入时随机的选取一个作为替换项(这时候池子里面有 k 项,可以使用 rand 函数)
这样的话,对于任意的 n ,都能保证每个数的选取概率都为 k/n,每个数选取概率相等,即随机。
证明如下:
重点在于每行被选取的概率的公式,理解之后,稍微化简一下就可以推导出来。