我有一个非常大的文本文件(~500MB),包含~100M行。 我想要完成的是尽可能快地从文件中随机抽样(大约)5M行到新文件中。
结果很灵活 - 必须是一个“足够好”的随机性,而不是一个完美的,并且采样行的数量可以非常接近5M,但不一定非精确。
我在这里有一个优势,即文件包含类似的长度行,这样可以更容易地使用第一行的大小来估计文件中的行数。
我的主要目标是运行时效率,因为我必须在数千个类似文件上执行此过程。
我已经检查了许多完成此操作的方法,从创建随机排序的行索引,然后在文件上运行,到reservoir sampling。
由于采样行的数量非常高(5M),因此排序预先计算的随机指数太昂贵,并且还在收集的样本上运行,因此水库采样非常昂贵。
我考虑过用随机“跳转”扫描文件,以创建文件的线性但随机扫描。 但是我仍然不确定以这样的方式完成这项工作的最佳方式是什么,即样本的随机性将尽可能均匀。
我可以在运行时效率甚至采样方面更好地使用此代码吗?
def random_sample_file(f_name, f_target, num_sampled_rows):
def _estimated_row_size(f):
return len(f.readline())
def _take_step():
return random.randint(row_size, max_leap)
file_size = os.path.getsize(f_name)
with open(f_name, 'rb') as f_in, open(f_target, 'w') as f_out:
row_size = _estimated_row_size(f_in)
max_leap = file_size / num_sampled_rows
for i in xrange(num_sampled_rows):
_step = _take_step()
f_in.seek(_step, 1)
_next_new_line = f_in.readline() # getting to the next new line (in case the pointer landed in the middle of a line)
f_out.write(f_in.readline())
return os.path.getsize(f_target)