2013-10-17 70 views
3

我有一個FASTA文件,可以很容易地被SeqIO.parse解析。Biopython SeqIO到Pandas Dataframe

我有興趣提取序列號和序列長度。我用這些行做的,但我覺得這是waaaay太沉重(兩次迭代,轉換等)

from Bio import SeqIO 
import pandas as pd 


# parse sequence fasta file 
identifiers = [seq_record.id for seq_record in SeqIO.parse("sequence.fasta", 
                  "fasta")] 
lengths = [len(seq_record.seq) for seq_record in SeqIO.parse("sequence.fasta", 
                  "fasta")] 
#converting lists to pandas Series  
s1 = Series(identifiers, name='ID') 
s2 = Series(lengths, name='length') 
#Gathering Series into a pandas DataFrame and rename index as ID column 
Qfasta = DataFrame(dict(ID=s1, length=s2)).set_index(['ID']) 

我只有一個迭代做到這一點,但我得到的字典:

records = SeqIO.parse(fastaFile, 'fasta') 

,我莫名其妙地不能得到DataFrame.from_dict工作...

我的目標是迭代FASTA文件,並獲得ID和序列長度爲DataFrame每次迭代。

這是一個short FASTA file爲那些誰想要幫助。

回答

3

你現貨 - 你絕對不應該在解析文件兩次,並在字典存儲的數據是計算資源的時候,你會僅僅是將其轉換爲numpy陣列後的浪費。

SeqIO.parse()返回一個生成器,這樣你就可以重複記錄的記錄,建立像這樣的列表:

with open('sequences.fasta') as fasta_file: # Will close handle cleanly 
    identifiers = [] 
    lengths = [] 
    for seq_record in SeqIO.parse(fasta_file, 'fasta'): # (generator) 
     identifiers.append(seq_record.id) 
     lengths.append(len(seq_record.seq)) 

解析只是ID和序列從FASTA文件的更有效的方法請參見Peter Cock's answer

其餘的代碼對我來說看起來不錯。但是,如果你真的想優化與pandas使用,您可以閱讀下面:


最大限度地減少內存使用

諮詢的source of panda.Series,我們可以看到,data被interally存儲爲numpyndarray

class Series(np.ndarray, Picklable, Groupable): 
    """Generic indexed series (time series or otherwise) object. 

    Parameters 
    ---------- 
    data: array-like 
     Underlying values of Series, preferably as numpy ndarray 

如果您identifiersndarray,它可以直接在使用如果不需要,不會構建新陣列(參數copy,默認False)將阻止創建新的ndarray。通過將序列存儲在列表中,您將強制Series將所述列表強制爲ndarray

避免初始化列表

如果你事先知道你到底有多少序列有(和最長的ID有多長),你可以初始化一個空ndarray持有的標識符,像這樣:

num_seqs = 50 
max_id_len = 60 
numpy.empty((num_seqs, 1), dtype='S{:d}'.format(max_id_len)) 

當然,很難確切知道你有多少個序列,或者最大的ID是什麼,所以最簡單的方法是讓numpy從現有的列表中進行轉換。但是,這是技術上最快的方式來存儲您的數據在pandas使用。

+0

感謝大衛,它做到了。也感謝「記憶」評論! – Sara

4

大衛給你的pandas側一個很好的答案,在Biopython側不需要通過Bio.SeqIO使用SeqRecord對象,如果你想要的是記錄標識符及其序列長度 - 這應該是更快:

from Bio.SeqIO.FastaIO import SimpleFastaParser 
with open('sequences.fasta') as fasta_file: # Will close handle cleanly 
    identifiers = [] 
    lengths = [] 
    for title, sequence in SimpleFastaParser(fasta_file): 
     identifiers.append(title.split(None, 1)[0]) # First word is ID 
     lengths.append(len(sequence))