因为要求从文件中选择的行具有统计上的均匀分布,所以我提供了这种简单的方法。
"""randsamp - extract a random subset of n lines from a large file"""
import random
def scan_linepos(path):
"""return a list of seek offsets of the beginning of each line"""
linepos = []
offset = 0
with open(path) as inf:
for line in inf:
linepos.append(offset)
offset += len(line)
return linepos
def sample_lines(path, linepos, nsamp):
"""return nsamp lines from path where line offsets are in linepos"""
offsets = random.sample(linepos, nsamp)
offsets.sort()
lines = []
with open(path) as inf:
for offset in offsets:
inf.seek(offset)
lines.append(inf.readline())
return lines
dataset = 'big_data.txt'
nsamp = 5
linepos = scan_linepos(dataset)
lines = sample_lines(dataset, linepos, nsamp)
print 'selecting %d lines from a file of %d' % (nsamp, len(linepos))
print ''.join(lines)
我在一个包含300万行、1.7GB的模拟数据文件上进行了测试。在我的不太好的桌面上,scan_linepos
占用了大约20秒的运行时间。
为了检查 sample_lines
的性能,我使用了 timeit
模块,如下所示:
import timeit
t = timeit.Timer('sample_lines(dataset, linepos, nsamp)',
'from __main__ import sample_lines, dataset, linepos, nsamp')
trials = 10 ** 4
elapsed = t.timeit(number=trials)
print u'%dk trials in %.2f seconds, %.2fµs per trial' % (trials/1000,
elapsed, (elapsed/trials) * (10 ** 6))
对于不同的
nsamp
值;当
nsamp
为100时,单个
sample_lines
完成时间为460微秒,并且随着样本量的线性增加,每次调用需要47毫秒。
接下来自然而然的问题是“
Python的随机数生成器真的随机吗?”,答案是“亚加密级别的,但对于生物信息学来说肯定足够了”。
islice
完成这个任务,在该帖子中,OP询问如何使用yield
完成此任务。 - Kev