Python 比较字符串列表中字符串中每个字符的最快方法

Python 比较字符串列表中字符串中每个字符的最快方法,python,bioinformatics,Python,Bioinformatics,我正在使用一个生物信息学工具,并使用两个循环来迭代每个角色 输入(即seq1和序列)是一串核苷酸,如长度相同的“AGATGCTAGTA”。sequence\u info是所有序列的列表 速度非常慢,因此我使用continue而不是添加零并将bio_数组存储为numpy数组,从而提高了速度。这是新代码 for (sequence, sequence_location) in sequence_info: value = slow_function(seq1, sequence) def

我正在使用一个生物信息学工具,并使用两个循环来迭代每个角色

输入(即seq1和序列)是一串核苷酸,如长度相同的“
AGATGCTAGTA”
sequence\u info
是所有序列的列表

速度非常慢,因此我使用continue而不是添加零并将
bio_数组存储为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_数组
,以获得相关值,然后对其求和:

>>> 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

你能给出一些输入和输出的例子来帮助其他人理解这个问题吗better@sshashank124,谢谢你让我知道,我添加了一个示例输入。请提供一些示例数据,并将您的示例转化为有效的示例,并说明实际问题:-您的示例引用了几个未指定的变量。您为什么返回
calc
?您将其保存到
value
中,但在每个循环中
value
将被覆盖,并且计算的值将丢失。
slow\u函数的结果似乎是
bio\u数组
中与
seq1
序列
的不匹配字符处于相同位置的元素的总和(假定长度相同)?请注意,
shorter\u slow\u function
的价值在于不依赖于numpy-在这个特定的简单示例中,仅使用Python列表和该函数将比将所有内容转换为numpy数组和使用
faster\u numpy\u function
更快。感谢时间分解。这非常有用。我将代码更改为be喜欢
shorter\u slow\u函数
。就像你提到的那样,将所有内容转换为numpy要比只使用不同的方法慢。非常感谢,这正是我想要的答案。但不幸的是,使用列表理解将列表中的每个元素转换为np.array所用的时间会增加太多的时间非常感谢你的回答。为什么不把整个东西一次转换成一个数组,然后你甚至可以在外部迭代中使用numpy,而不是在循环中使用
。不幸的是,这是我第一次做的。我认为我的问题有点不足以得到答案,所以我会放弃ed建议您按照@Boendal的建议进行parrellization,或者直接用C编写,看看是否有帮助。只要您避免手动循环,并停留在numpy域中,使用正确的惯用numpy代码,您应该能够获得非常好的性能。我会首先尝试重构代码,以避免这些手动
for
尽可能多地循环,在尝试更剧烈的更改(如用另一种语言重写)之前,谢谢,我将尝试删除所有循环手册,并使用适当的numpy代码来查看如何最好地提高速度。