随机下采样一个大文件

时间:2018-02-11 10:27:07

标签: python performance io bioinformatics coding-efficiency

我有一个非常大的文本文件(~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)

0 个答案:

没有答案
相关问题