2015-09-16 10 views
5

Mam serię wejścia plików, takich jak:linie rozdzielające z "z INFILE w python

chr1 hg19_refFlat exon 44160380 44160565 0.000000 + . gene_id "KDM4A"; transcript_id "KDM4A"; 
chr1 hg19_refFlat exon 19563636 19563732 0.000000 - . gene_id "EMC1"; transcript_id "EMC1"; 
chr1 hg19_refFlat exon 52870219 52870551 0.000000 + . gene_id "PRPF38A"; transcript_id "PRPF38A"; 
chr1 hg19_refFlat exon 53373540 53373626 0.000000 - . gene_id "ECHDC2"; transcript_id "ECHDC2_dup2"; 
chr1 hg19_refFlat exon 11839859 11840067 0.000000 + . gene_id "C1orf167"; transcript_id "C1orf167"; 
chr1 hg19_refFlat exon 29037032 29037154 0.000000 + . gene_id "GMEB1"; transcript_id "GMEB1"; 
chr1 hg19_refFlat exon 103356007 103356060 0.000000 - . gene_id "COL11A1"; transcript_id "COL11A1"; 

w moim kodu Próbuję uchwycić 2 elementy z każdej linii, pierwszy to numer po którym mówi eksonu, drugi gen (numer i się combo otoczony „”, na przykład „KDM4A” Oto mój kod.

with open(infile,'r') as r: 
     start = set([line.strip().split()[3] for line in r]) 
     genes = set([line.split('"')[1] for line in r]) 
     print len(start) 
     print len(genes) 

jakiegoś początku powód działa dobrze, ale geny niczego nie robienia. Oto wynik:

48050 
0 

ja figura to jest coś zrobić z „” otaczającej nazwy genów ale jeśli wejdę to na terminalu działa dobrze:

>>> x = 'A b P "G" m' 
>>> x 
'A b P "G" m' 
>>> x.split('"')[1] 
'G' 
>>> 

Wszelkie rozwiązania będą mile widziane? Nawet jeśli jest to zupełnie inny sposób przechwytywania 2 elementów danych z każdej linii. Dzięki

Odpowiedz

8

to dlatego Twój obiekt plik zostanie wyczerpany, gdy pętla nad nim raz tutaj start = set([line.strip().split()[3] for line in r]) znowu próbujesz pętli tutaj genes = set([line.split('"')[1] for line in r]) nad wyczerpanym obiektu pliku

Rozwiązanie:

Można dążyć do początek pliku (jest to jedno z rozwiązań)

Modyfikacja kodu:

with open(infile,'r') as r: 
    start = set([line.strip().split()[3] for line in r]) 
    r.seek(0, 0) 
    genes = set([line.split('"')[1] for line in r]) 
    print len(start) 
    print len(genes) 
+0

Ok, więc co należy OP zrobić? – Kevin

+0

@Kevin edytowane dzięki – The6thSense

+0

dzięki, nie natknąłem się na metodę wyszukiwania wcześniej, bardzo przydatne. Akceptuję tę odpowiedź, ponieważ jest ona najkrótsza i najbardziej zwięzła oraz rozwiązuje problem z 1 krótką linią kodu – user3062260

4

Możesz użyć wyrażenia regularnego.

with open(file) as f: 
    start = [] 
    genes = [] 
    for line in f: 
     st, gen = re.search(r'\bexon\s+(\d+)\b.*?\s+gene_id\s+"([^"]*)"', line).groups() 
     start.append(st) 
     genes.append(gen) 
    print set(start) 
    print set(genes) 

DEMO

+0

Teraz masz dwa problemy! –

+0

Ale czy 'start' i' geny' nie będą teraz ciągami zamiast setów? Wygląda całkiem inaczej niż początkowo OP. – Kevin

+0

@Kevin dobry połów .. Teraz jest ok, myślę, że ... –

2

Można załadować wszystkie wiersze na liście, a następnie wykonać split na każdej pozycji w tej liście (nie wiem, jak skuteczne jest to, czy plik jest długa)

with open(infile) as r: 
    lines = [line for line in r] 
    start = set([line.strip().split()[3] for line in lines]) 
    genes = set([line.split('"')[1] for line in lines]) 
+0

Myślałem o tym, ale plik jest masywny i muszę przechodzić przez 24 pliki o podobnych rozmiarach, więc zajmie to całe wieki. – user3062260

2

Używanie shlex (jak to jest w przypadku argumentów powłoki), neutralizuje wiele spacji i cytatów.
Nie jestem pewien, czy jest szybszy, ale bezpieczny i miły.

import shlex 
with open(infile, 'r') as f: 
    for line in f: 
     parts = shlex.split(line.replace(';', '')) 
     print parts[3], parts[9] 
+0

Nie spotkałem się wcześniej z shlexem i wydaje się, że działa to całkiem nieźle. Zresetowanie pętli wydaje się jednak najprostszym rozwiązaniem. – user3062260

2

Przyczyną, dla której nie udało się załadować genes jest konieczność ponownego uruchomienia odczytu pliku od początku. Poniższa metoda chociaż powinno działać:

import re 

start = set() 
genes = set() 

with open('input.txt', 'r') as f_input: 
    for line in f_input: 
     s, g = re.match(r'(?:.*?\s+){3}(\d+).*"(\w+)"', line).groups() 
     start.add(s) 
     genes.add(g) 

print start 
print genes 

Dając wyjście:

set(['44160380', '29037032', '103356007', '19563636', '53373540', '52870219', '11839859']) 
set(['COL11A1', 'PRPF38A', 'KDM4A', 'C1orf167', 'EMC1', 'GMEB1', 'ECHDC2_dup2'])