我编写了一个函数来计算某些字符(A
、C
、G
和 T
) 在同一位置的多个字符串中,并将出现的次数保存在字典中。
例如对于这两个字符串 'ACGG' 和 'CAGT',它应该返回:
{'A': [1, 1, 0, 0], 'C': [1, 1, 0, 0], 'G': [0, 0, 2, 1], 'T': [0, 0, 0, 1]}
我想将下面的代码转换为列表理解以优化它的速度。它使用两个嵌套的 for 循环,输入的 Motifs 是包含 A's C's G's 和 T's 的字符串列表。
def CountWithPseudocounts(Motifs):
count = {}
k = len(Motifs[0])
t = len(Motifs)
for s in 'ACGT':
count[s] = [0] * k
for i in range(t):
for j in range(k):
symbol = Motifs[i][j]
count[symbol][j] += 1
return count
我已经尝试为这个列表理解替换函数底部的嵌套 for 循环:
count = [ [ count[Motifs[i][j]][j] += 1 ] for i in range(0, t) ] for j in range(0, k)]
它不起作用,可能是因为我不允许在列表推导中进行 += 1 的赋值。我该如何解决这个问题?
最佳答案
你可以使用zip()
:
In [10]: a = 'ACGG'
In [11]: b = 'CAGT'
In [12]: chars = ['A', 'C', 'G', 'T']
In [13]: [[(ch==i) + (ch==j) for i, j in zip(a, b)] for ch in chars]
Out[13]: [[1, 1, 0, 0], [1, 1, 0, 0], [0, 0, 2, 1], [0, 0, 0, 1]]
如果你想要一本字典,你可以使用字典理解:
In [25]: {ch:[(ch==i) + (ch==j) for i, j in zip(a, b)] for ch in chars}
Out[25]: {'T': [0, 0, 0, 1], 'G': [0, 0, 2, 1], 'C': [1, 1, 0, 0], 'A': [1, 1, 0, 0]}
或者,如果您希望结果与字符列表的顺序相同,您可以使用 collections.OrderedDict
:
In [26]: from collections import OrderedDict
In [27]: OrderedDict((ch, [(ch==i) + (ch==j) for i, j in zip(a, b)]) for ch in chars)
Out[28]: OrderedDict([('A', [1, 1, 0, 0]), ('C', [1, 1, 0, 0]), ('G', [0, 0, 2, 1]), ('T', [0, 0, 0, 1])])
如果您仍然需要更高的性能和/或您正在处理长字符串和更大的数据集,您可以使用 Numpy 通过矢量化方法来解决这个问题。
In [61]: pairs = np.array((list(a), list(b))).T
In [62]: chars
Out[62]:
array(['A', 'C', 'G', 'T'],
dtype='<U1')
In [63]: (chars[:,None,None] == pairs).sum(2)
Out[63]:
array([[1, 1, 0, 0],
[1, 1, 0, 0],
[0, 0, 2, 1],
[0, 0, 0, 1]])
关于python - 替换嵌套的 for 循环和列表理解的值分配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42672276/