This is a follow up to my previous question (text file reduction with randomization in Python). Was modifying to run through multiple reductions, but only the first output file contains reductions, the following 3 files are zero size. This must be something obvious I am not seeing...
#!/usr/bin/env python
import random
import sys
from itertools import chain, groupby
def choose_random(iterator, fraction, random=random.random):
"""Lazy analog of:
L = list(iterator)
k = int(len(L) * fraction + .5) or 1 # get at least one
result = random.sample(L, k)
Note: this function doesn't randomize the order of elements
that would require to keep selected elements in memory
and number of output elements is not exactly k
"""
# always yield at least one item if input is not empty
item = next(iterator)
it = (x for x in chain([item], iterator) if random() < fraction)
for x in chain([next(it, item)], it):
yield x
def getkey(line):
return line.split("\t")[3] # 4th column
reductions = [0.25, 0.50, 0.75, 1]
filename = "foo"
outfile = [open("-".join([x, filename]), "w") for x in map(str, reductions)]
try:
with open(filename, "r") as f:
for ln, k in enumerate(map(float, reductions)):
for key, group in groupby(f, key=getkey):
outfile[ln].writelines(choose_random(group, fraction=k))
finally:
for f in outfile:
f.close()
output shows up like this (file 0.25-foo contains correct reduction, the rest are empty):
-rw-r--r-- 1 staff staff 53326048 Mar 27 03:42 0.25-foo
-rw-r--r-- 1 staff staff 0 Mar 27 03:42 0.5-foo
-rw-r--r-- 1 staff staff 0 Mar 27 03:42 0.75-foo
-rw-r--r-- 1 staff staff 0 Mar 27 03:42 1-foo
You open foo
once, but try to iterate over it four times. By the end of the first reduction, you're at the end of file. Either reopen it:
try:
for ln, k in enumerate(map(float, reductions)):
with open(filename, "r") as f:
for key, group in groupby(f, key=getkey):
outfile[ln].writelines(choose_random(group, fraction=k))
finally:
for f in outfile:
f.close()
or rewind after each reduction:
try:
with open(filename, "r") as f:
for ln, k in enumerate(map(float, reductions)):
for key, group in groupby(f, key=getkey):
outfile[ln].writelines(choose_random(group, fraction=k))
f.seek(0)
finally:
for f in outfile:
f.close()
I'd open both files at one point:
reductions = [0.25, 0.50, 0.75, 1.0]
filename = "foo"
for fraction in reductions:
with open(filename, "r") as f, open('%s-%s' % (fraction, filename), 'w') as outfile:
for key, group in groupby(f, key=getkey):
outfile.writelines(choose_random(group, fraction=fraction))