2014-10-06 3 views
1

Привет я написал простой код в Python, чтобы сделать следующее:получить номера без согласования линии питона

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

file_1:

R000002 
R000003 
R000006 

второй файл имеет имена и положение всех моих локусов и выглядит следующим образом:

file_2:

R000001 1 
R000001 2 
R000001 3 
R000002 10 
R000002 2 
R000002 3 
R000003 20 
R000003 3 
R000004 1 
R000004 20 
R000004 4 
R000005 2 
R000005 3 
R000006 10 
R000006 11 
R000006 123 

То, что я хочу сделать, это получить все соответствующие номера строк локусов из Файл2, которые не File1, так что конечный результат должен выглядеть следующим образом :

Результат:

1 
2 
3 
9 
10 
11 
12 
13 

Я написал следующий простой код и он получает работу

#!/usr/bin/env python 

import sys 

File1 = sys.argv[1] 
File2 = sys.argv[2] 

F1 = open(File1).readlines() 
F2 = open(File2).readlines() 
F3 = open(File2 + '.np', 'w') 
Loci = [] 

for line in F1: 
     Loci.append(line.strip()) 

for x, y in enumerate(F2): 
     y2 = y.strip().split() 
     if y2[0] not in Loci: 
       F3.write(str(x+1) + '\n') 

Однако, когда я бегу это на моем реальном наборе данных, где первый файл имеет 58470 строк и второй файл имеет 12881010 строк, которые, кажется, уходят навсегда. Я предполагаю, что узкое место в

if y2[0] not in Loci: 

части, где код должен искать через всю file_2 неоднократно, но я не смог найти более быстрое решение.

Может кто-нибудь помочь мне и показать более питонический способ делать что-то.

Заранее спасибо

+0

Ваши файлы заказываются? –

+0

да, они оба заказаны. Однако только некоторые из локусов в File2 находятся в File_1, а File1 не идет последовательно. Значение в File_1 вы можете перейти с R00на R000255. – iksaglam

+0

Для начала вы можете сделать 'Loci' в' set' вместо 'list'. Это наверняка улучшит время поиска. – sberry

ответ

2

Вот некоторые немного более Pythonic код, который не заботится, если файлы упорядочены. Я бы предпочел просто распечатать все и перенаправить его в файл ./myscript.py > outfile.txt, но вы также можете передать другое имя файла и написать на него.

#!/usr/bin/env python 
import sys 

ignore_f = sys.argv[1] 
loci_f = sys.argv[2] 

with open(ignore_f) as f: 
    ignore = set(x.strip() for x in f) 

with open(loci_f) as f: 
    for n, line in enumerate(f, start=1): 
     if line.split()[0] not in ignore: 
      print n 

Поиск чего-либо в списке - это O (n), тогда как для набора требуется только O (1). Если заказ не имеет значения, и у вас есть уникальные вещи, используйте set над списком. Хотя это не оптимально, оно должно быть O (n) вместо O (n × m), как ваш код.

Вы также не закрываете свои файлы, которые при чтении из них не так важны, но при написании. Я использую контекстные менеджеры (with), поэтому Python делает это для меня.

Стиль-мудрый, использовать описательные имена переменных. и избегайте имен UpperCase, которые обычно используются для классов (см. PEP-8).

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

0

Чтобы сделать поиск совпадений более эффективно вы можете просто использовать set вместо list:

Loci = set() 

for line in F1: 
    Loci.add(line.strip()) 

Остальные должны работать так же, но быстрее.

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

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