2013-03-23 2 views
0

У меня есть 1000 .txt файлов, на которых я запускаю этот код. Мне нужно найти наибольшее значение ENSG в файлах и удалить другие значения ENSG, которые меньше, чем самые большие. Затем мне нужно найти минимальное значение из того же текстового файла, просмотрев длину utr и сохраните его в моем файле output.txt. Я хочу, чтобы вывод 1000 .txt файлов в 1 output.txt файла. Этот код работает примерно нормально, но он перезаписывает результат. Это показывает только результат последнего файла:Поиск минимального значения слова из большого количества файлов в python?

import glob 
f2 = glob.glob("./*.txt") 
all_text="" 
for fpath in f2: 
    f = open(fpath,"r") 
    list_lines = f.readlines() 
    dic={} 
    sent="ENSG" 
    temp_list=[] 
    for line in list_lines: 
     all_text=all_text+line 
     name= line.rsplit()[0].strip() 
     score=line.rsplit()[1].strip() 
     dic[name]=score 
    for i in dic.keys(): 
     if sent in i: 
      temp_list.append(dic[i]) 
      hiegh_score=max(temp_list) 
    def check(index): 
     reverse_text=all_text[index+1::-1] 
     index2=reverse_text.find("\n") 
     if sent==reverse_text[:index2+1][::-1][1:len(sent)+1]: 
      return False 
     else: 
      return True 

    list_to_min=dic.values() 
    for i in temp_list: 
     if i!=hiegh_score: 
      index=all_text.find(str(i)) 
      while check(index): 
       index=all_text.find(str(i),index+len(str(i))) 
      all_text=all_text[0:index]+all_text[index+len(str(i)):] 
      list_to_min.remove(str(i)) 
file2=open("my_try4.txt","w") 
file2.write(all_text) 
min_score= min(list_to_min) 
for j in dic.keys(): 
    if min_score==dic[j]: 
     k="min score is :"+str(min_score)+" for person "+j 
     file2.write(k) 
print "%6d : %s" % (len(list_lines),fpath) 
file2.close() 
f.close() 

У меня есть текстовые файлы, как этот 4.txt:

ENSBTAG00000020679 197 
ENSCAFG00000009872 2585 
ENSG00000018236 1935 
ENSG00000018236 230 
ENSG00000018236 257 
ENSG00000018236 338 
ENSG00000018236 922 
ENSG00000018236 922 
ENSRNOG00000004438 14 
ENSRNOG00000004438 14 

Теперь он должен выбрать ENSG с 1935 и удалить все другие значения ENSG. Теперь текстовый файл должен выглядеть следующим образом:

ENSBTAG00000020679 197 
    ENSCAFG00000009872 2585 
    ENSG00000018236 1935 
    ENSRNOG00000004438 14 
    ENSRNOG00000004438 14 

И теперь, глядя на этот текстовый файл, мы находим кратчайшее значение и сохранить его в текстовом файле (мы делаем это на 1000 файлов и вывод должен быть на 1 файл).

output.txt 
textfile4 14 
+1

Http: //hyperboleandahalf.blogspot. co.uk/2010/04/alot-is-better-than-you-at-everything.html Извините, не смог устоять :) – Thomas

+0

Правильно ли это отступ? У вас есть 'open' в цикле и' close' в наибольшей степени. – hughdbrown

+0

Ваш вопрос трудно понять, и ваш код еще сложнее понять. Не могли бы вы перефразировать? Почему следует, что выбрано «14»? (Что значит «выбрано»?) Хотите ли вы получить набор самых больших значений «ENSG»-префикса для каждого файла, а затем минимальное значение из этого набора самых больших значений? –

ответ

1

Это было легче переписать, чем выяснить, что случилось с вашим кодом:

import os.path 
import glob 
import re 
import itertools 
from collections import namedtuple, deque 
from operator import attrgetter 

R_PREFIX_VALUE = re.compile(r'^(?P<prefix>[A-Z]+)(?P<suffix>\d+)\s+(?P<value>\d+)\s*$') 

getvalue = attrgetter('value') 

def interleave(seq, val): 
    return itertools.chain.from_iterable(itertools.izip(seq, itertools.repeat(val))) 

class Fileline(namedtuple('Fileline', 'filename prefix suffix value')): 
    @classmethod 
    def _fromstr(cls, s, filename=None, rematch=R_PREFIX_VALUE.match): 
     m = rematch(s) 
     if not m: 
      raise ValueError('No valid line found in %r' % s) 
     d = m.groupdict() 
     d['value'] = int(d['value']) 
     d['filename'] = filename 
     return cls(**d) 

    def _asstr(self): 
     return '{}{} {}'.format(self.prefix, self.suffix, self.value) 

def max_value_with_prefix(lineseq, prefix, getvalue=getvalue): 
    withprefix = (line for line in lineseq if line.prefix==prefix) 
    return max_value(withprefix) 

def filter_lt_line(lineseq, maxline): 
    for line in lineseq: 
     if line.prefix != maxline.prefix or line.value >= maxline.value: 
      yield line 

def extreme_value(fn, lineseq, getvalue=getvalue): 
    try: 
     return fn((l for l in lineseq if l is not None), key=getvalue) 
    except ValueError: 
     return None 

def max_value(lineseq): 
    return extreme_value(max, lineseq) 

def min_value(lineseq): 
    return extreme_value(min, lineseq) 

def read_lines(fn, maker=Fileline._fromstr): 
    with open(fn, 'rb') as f: 
     return deque(maker(l, fn) for l in f) 

def write_file(fn, lineseq): 
    lines = (l._asstr() for l in lineseq) 
    newlines = interleave(lines, '\n') 
    with open(fn, 'wb') as f: 
     f.writelines(newlines) 

def write_output_file(fn, lineseq): 
    lines = ("{} {}".format(l.filename, l.value) for l in lineseq) 
    newlines = interleave(lines, "\n") 
    with open(fn, 'wb') as f: 
     f.writelines(newlines) 

def filter_max_returning_min(fn, prefix): 
    lineseq = read_lines(fn) 
    maxvalue = max_value_with_prefix(lineseq, prefix) 
    filteredlineseq = deque(filter_lt_line(lineseq, maxvalue)) 
    write_file(fn, filteredlineseq) 
    minline = min_value(filteredlineseq) 
    return minline 

def main(fileglob, prefix, outputfile): 
    minlines = [] 
    for fn in glob.iglob(fileglob): 
     minlines.append(filter_max_returning_min(fn, prefix)) 
    write_output_file(outputfile, minlines) 

точка входа main(), который называется как main('txtdir', 'ENSG', 'output.txt'). Для каждого файла filter_max_returning_min() откроет и перепишет файл и вернет значение min. Нет необходимости хранить диктовку или список каждой строки каждого файла, который вы посетили.

(BTW, деструктивно перезапись файлов кажется плохой идеей! Рассматривали ли вы копировать их в другом месте?)

При изолируют отдельные проблемы в отдельные функции, становится очень легко переформировать их различное поведение исполнения. Например, это тривиально, чтобы запустить эту задачу на все файлы параллельно, добавив две небольшие функции:

def _worker(args): 
    return filter_max_returning_min(*args) 

def multi_main(fileglob, prefix, outputfile, processes): 
    from multiprocessing import Pool 
    pool = Pool(processes=processes) 
    workerargs = ((fn, prefix) for fn in glob.iglob(fileglob)) 
    minlines = pool.imap_unordered(_worker, workerargs, processes) 
    write_file(outputfile, minlines) 

Теперь вы можете запустить настраиваемое количество рабочих, каждый из которых будет работать на один файл, и собирать их мин, когда они сделаны. Если у вас очень большие файлы или большое количество файлов и они не связаны с IO, это может быть быстрее.

Просто для удовольствия, вы можете легко превратить это утилита CLI:

def _argparse(): 
    import argparse 

    def positive_int(s): 
     v = int(s) 
     if v < 1: 
      raise argparse.ArgumentTypeError('{:r} must be a positive integer'.format(s)) 
     return v 

    parser = argparse.ArgumentParser(
     formatter_class=argparse.RawDescriptionHelpFormatter, 
     description="""Filter text files and write min value. 

    Performs these operations on the text files in supplied `filedir`: 

    1. In each file, identify lines starting with the matching `maxprefix` 
     which do *not* contain the maximum value for that prefix in that file. 
    2. DESTRUCTIVELY REWRITE each file with lines found in step 1 removed! 
    3. Write the minimum value (for all lines in all files) to `outputfile`. 
    """) 
    parser.add_argument('filedir', 
     help="Directory containg the text files to process. WILL REWRITE FILES!") 
    parser.add_argument('maxprefix', nargs="?", default="ENSG", 
     help="Line prefix which should have values less than max value removed in each file") 
    parser.add_argument('outputfile', nargs="?", default="output.txt", 
     help="File in which to write min value found. WILL REWRITE FILES!") 
    parser.add_argument('-p', '--parallel', metavar="N", nargs="?", type=positive_int, const=10, 
     help="Process files in parallel, with N workers. Default is to process a file at a time.") 
    return parser.parse_args() 

if __name__ == '__main__': 
    args = _argparse() 
    fileglob = os.path.join(args.filedir, '*.txt') 
    prefix = args.maxprefix 
    outputfile = args.outputfile 
    if args.parallel: 
     multi_main(fileglob, prefix, outputfile, args.parallel) 
    else: 
     main(fileglob, prefix, outputfile) 

Теперь вы можете вызвать его из командной строки:

$ python ENSG.py txtdir ENSCAFG --parallel=4 
+0

Возможно, вы захотите объяснить это немного больше, чтобы довести его до уровня OP Python; также 'int (s)' будет поднимать 'ValueError', если передается что-то не числовое. –

+0

@Francis Avila Я понимаю, что вы хотите сказать, вы принимаете хороший способ дать мне понять, как программист может написать хороший код, спасибо за это, так как ваш код кажется более умным и легким, чем мое кодирование. – Rocket

+0

Doesn Кажется, что он нашел какие-то файлы, и поэтому он не записал минимум. Являются ли ваши текстовые файлы в 'txtdir'? –

Смежные вопросы