2016-06-01 1 views
1

j'ai un fichier FASTA comme suit:lignes Concaténation à une chaîne en python

>scaf1 
AAAAAATGTGTGTGTGTGTGYAA 
AAAAACACGTGTGTGTG 
>scaf2 
ACGTGTGTGTGATGTGGY 
AAAAAATGTGNNNNNNNNYACGTGTGTGTGTGTGTACACWSK 
>scaf3 
AAAGTGTGTTGTGAAACACACYAAW 

Je veux le lire dans un dictionnaire dans une suite que plusieurs lignes appartenant à une séquence aller à une touche, la sortie serait:

{'scaf1': 'AAAAAATGTGTGTGTGTGTGYAAAAAAACACGTGTGTGTG', 'scaf2': 'ACGTGTGTGTGATGTGGYAAAAAATGTGNNNNNNNNYACGTGTGTGTGTGTGTACACWSK', 'scaf3': 'AAAGTGTGTTGTGAAACACACYAAW'} 

Le script que je l'ai écrit est:

import sys 
from collections import defaultdict 

fastaseq = open(sys.argv[1], "r") 

def readfasta(fastaseq): 
    fasta_dict = {} 
    for line in fastaseq: 
     if line.startswith('>'): 
      header = line.strip('\n')[1:] 
      sequence = '' 
     else: 
      sequence = sequence + line.strip('\n') 
     fasta_dict[header] = sequence 
    return fasta_dict 

fastadict = readfasta(fastaseq) 
print fastadict 

Il fonctionne correctement et rapide pour un tel fi mais quand la taille du fichier augmente (c'est-à-dire environ 1,5 Gb), alors cela devient trop lent. L'étape qui prend du temps est la partie concaténation du sequence. Je me demandais s'il y avait une façon plus rapide de concaténer les lignes à une seule chaîne?

+1

séquence Peut-être que '+ = line.strip (...)' sera plus rapide, parce qu'ici vous n'êtes pas extraire la valeur de ' sequence', en lui ajoutant des données, puis en l'assignant à 'sequence' à nouveau. Juste '+ =' et c'est tout. – ForceBru

+0

Juste changé dans mon script, il a en effet augmenté la vitesse, merci! – Homap

Répondre

5

La concaténation de chaînes avec + nécessite la création d'une nouvelle chaîne, car les chaînes Python sont immuables, ce qui est une consommation de temps.

Utilisez str.join pour les concaténer après toutes les chaînes sont prêts,

import sys 

def read_fasta(filename): 
    fasta_dict = {} 
    l = list() 
    header = None 
    with open(filename, 'r') as f: 
     for line in f: 
      if line.startswith('>'): # a new record 
       # save the previous record to the dict 
       if header: 
        fasta_dict[header] = ''.join(l) 
        del l[:] # empty the list 

       header = line.strip().split('>')[1] 
      else: 
       l.append(line.strip()) 

     # save the last record 
     fasta_dict[header] = ''.join(l) 

    return fasta_dict 

fastadict = read_fasta(sys.argv[1]) 
print(fastadict) 
+1

Oui, l'utilisation d'une liste et de 'joining 'à la fin semble être une bonne idée ici. Je suppose que l'ajout d'éléments à une liste est généralement plus rapide que leur concaténation à une chaîne (quelque chose comme O (1) vs O (N)). Pour un en-tête avec un nombre substantiel de lignes suivantes (disons, 100), je m'attendrais à une augmentation de performance mesurable. – Kevin

+1

Extrêmement plus rapide, merci! – Homap