我正在使用一种生物信息学工具,并使用两个循环遍历每个字符来构造它。
输入(即seq1和序列)是长度相同的核苷酸字符串,例如'AGATGCTAGTA'
。 sequence_info
是所有序列的列表。
速度非常慢,因此我通过使用Continue而不是加零并将bio_array
存储为numpy数组来提高了速度。这是新代码。
for (sequence, sequence_location) in sequence_info:
value = slow_function(seq1, sequence)
def slow_function(seq1,sequence):
calc=0
for i,nt in enumerate(seq1):
if nt == sequence[i]:
continue
else:
calc += bio_array[i]
return float(calc)
在jupyter笔记本电脑中使用%%timeit
,它仍然在100ms
附近。我需要它在1-5ms
左右或以下。我尝试过将函数转换为迭代器,并使用列表推导/映射而不是使用循环。但是这些方法并未产生重大影响。
我认为可以使用numpy,但我无法通过查看文档或在stackoverflow上找到要使用的方法。如果序列中有不匹配项,我需要将bio_array
中的特定值相加,因此我需要分别比较字符串中的每个字符值。
将这种代码的速度尽快提高的最佳方法是什么?
如果我理解正确,您的问题是,您希望基于两个字符串序列不匹配的位置求和数组元素。您可以简单地创建序列的字符数组,然后使用numpy条件索引来获取不匹配的值。这是一个简化的示例:
seq_a = np.array(list('ABCDEFGH'))
seq_b = np.array(list('ABCZEFZH'))
bio_array = np.array([1, 5, 9, 4, 3, 8, 2, 7])
然后,在seq_a
和seq_b
之间进行逐元素比较会得出:
>>> seq_a != seq_b
array([False, False, False, True, False, False, True, False])
然后您可以用此结果索引bio_array
以获取相关值,然后将它们求和:
>>> bio_array[seq_a != seq_b]
array([4, 2])
>>> bio_array[seq_a != seq_b].sum()
6
您应该接受@ sshashank124的回答,但是这里有一些简短的代码来说明正在发生的事情以及它的不同之处:
import numpy as np
from timeit import timeit
def slow_function(seq1, seq2, costs):
calc = 0
for i, nt in enumerate(seq1):
if nt == seq2[i]:
continue
else:
calc += costs[i]
return float(calc)
def shorter_slow_function(seq1, seq2, costs):
return sum(costs[i] for i in range(len(seq1)) if seq1[i] != seq2[i])
def faster_numpy_function(seq1, seq2, costs):
return costs[seq1 != seq2].sum()
x = np.array(list('ABCDE'))
y = np.array(list('XBCDY'))
c = np.array([1.0, 2.0, 3.0, 4.0, 5.0])
print(timeit(lambda: slow_function(x, y, c)))
print(timeit(lambda: shorter_slow_function(x, y, c)))
print(timeit(lambda: faster_numpy_function(x, y, c)))
结果:
6.7421024
6.665790399999999
5.321171700000001