转自:
https://dylanwu.iteye.com/blog/1318657
在建模的时候,时常需要构造训练集和测试集,但当总数据比较大的时候,如何进行简单抽样也是一个问题。
假设有这样一个情况,一份数据总共有1,000,000条,要从中抽取100,000条左右的数据。每条数据相对比较大,把所有数据一次放入内存不靠谱,那么如何抽样呢?
最龊的方法就是抽取头100,000或100,000条。
第二种能想到的方法就是,构造一个1-1,000,000的数组,然后从里面随机抽取100,000个作为样本行号列表,在读取大文件,一旦行号在列表中就输出到样本文件中。
第二种方法基本够用,但还是存在一定缺陷。当总数据非常大,需要抽取的样本数也不小时,或机器内存较小时。于是考虑到使用概率方式,在[1-n]作均匀随机抽取数字,那么期望值(n+1)/2,也就是说随机足够多次数,那么所有的随机出来的数字的平均数为(n+1)/2。那么是否可以这样考虑,我们每随机一个值a,就把大文件中中连续的a行作为一个块,那么最后每个块的平均大小为(n+1)/2,也就是说大文件被切分成N/((n+1)/2),我们再再每一块中取一行作为样本。这样的话由于大文件的总行数N,和块数(样本大小)是已知的,那么我们就可以求出n。
还是一开始的例子,可以求出n=(N/m) * 2 - 1=(1000000/100000) * 2 - 1 = 19;
于是
Python代码:
ei=randint(1, 19);bi=0;
fd = open('total.txt', 'r');
ofd = open('sample.txt', 'w');
while True:
line = fd.readline();
if not line:
break;
bi += 1;
if bi != ei:
continue;
ofd.write(line);
bi = 0;
ei = randint(1, 19)
PS: 我实际测试的列子是总数据条数为35385665,尝试抽取100,000,使用上面的方法,最后抽取出100,167条记录,基本符合要求了。不过不能精确的抽取100,000也就是这个方法的弊端了。
转自: https://dylanwu.iteye.com/blog/1318657