ファイルから選択された行が統計的に均一に分布しているという要件が追加されたため、この単純なアプローチを提供します。
"""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:
# WARNING: CPython 2.7 file.tell() is not accurate on file.next()
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() # this may make file reads more efficient
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) # the scan only need be done once
lines = sample_lines(dataset, linepos, nsamp)
print 'selecting %d lines from a file of %d' % (nsamp, len(linepos))
print ''.join(lines)
ディスク上の1.7GBを構成する300万行のモックデータファイルでテストしました。私の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
;のさまざまな値について 100のときnsamp
、シングルsample_lines
は460µsで完了し、呼び出しごとに47msで最大10kサンプルまで線形にスケーリングされました。
次の自然な質問は、ランダムはほとんどランダムではないということです。、そして答えは「サブ暗号ですが、バイオインフォマティクスには確かに問題ありません」です。