通过python计算一个fasta中的20-mer数字

时间:2018-05-15 14:10:13

标签: python csv biopython fasta

读取长度为120 nt的常规fasta文件:'single_mapped.fa'

一个CSV文件包含10000个20-mer和每个20mer的计数:'20frequent_20mers.txt',如下所示:

AAAAAGTATAGGAGATAGAA    35
AAAAATAGGAGGACTATTCA    26
AAAAATAGGAGGACTATTTA    24
AAAAATAGGAGGCCTATTCA    62

我想通过single_mapped.fa,计算每次读取20frequent_20mers.txt中所有20-mer的累计计数,即读取:

AAAAAGTATAGGAGATAGAA AAAAATAGGAGGACTATTCA,我想要61(35 + 26)

我的代码:

file2 = open('20frequent_20mers.txt','r')
kmer_list = csv.reader(file2, delimiter='\t')

for seq_record in SeqIO.parse("single_mapped.fa", "fasta"):
    print(seq_record.id)
    score_fre = 0
    sequence_string = str(seq_record.seq)
    for i in range(0,101):
            seq = sequence_string[i:i+20]
            for row in kmer_list:
                if row[0] == seq:
                    score_fre = score_fre + int(row[1])            
    print(score_fre)

当我单独运行它们时,每个循环都运行良好,但是没有像上面那样工作,有人能告诉我哪里出错了吗?或者是否有更聪明有效的方法来做到这一点?提前谢谢!

2 个答案:

答案 0 :(得分:2)

使用您拥有的代码,您需要从头开始为每个序列和i值重新读取您的kmer文件。这将是非常缓慢的,应该避免。由于您没有将文件指针移回到开头,因此它只能工作一次。

可以通过在for row in kmer_list:行之前添加来移动文件指针:

file2.seek(0)

更好的方法是首先将所有kmer条目加载到字典中以及相应的计数。这样他们就可以快速查找:

import csv

kmers = {}

with open('20frequent_20mers.txt') as f_kmers:
    for kmer, count in csv.reader(f_kmers, delimiter='\t'):
        kmers[kmer] = int(count)

for seq_record in SeqIO.parse("single_mapped.fa", "fasta"):
    print(seq_record.id)
    score_fre = 0
    sequence_string = str(seq_record.seq)

    for i in range(0, 101):
        seq = sequence_string[i:i+20]
        score_fre += kmers.get(seq, 0)

    print(score_fre) 

如果在字典中找不到seq,则返回默认值0

答案 1 :(得分:0)

使用@MartinEvans词典的替代实现(不一定更好,也不一定更快),但使用re.findall()生成kmers进行测试,并使用mapsum而不是(显式)内部循环:

from Bio import SeqIO
from re import findall
from itertools import repeat

kmers = {}

with open('20frequent_20mers.txt') as f_kmers:
    for line in f_kmers:
        kmer, count = line.strip().split('\t')
        kmers[kmer] = int(count)

for seq_record in SeqIO.parse("single_mapped.fa", "fasta"):
    print(seq_record.id)

    # use forward lookahead to make findall() find overlapping results;

    score_fre = sum(map(kmers.get, findall(r'(?=([ACTG]{20}))', str(seq_record.seq)), repeat(0)))

    print(score_fre)