2013-05-02 90 views
0

给定每个数据点的两个数据序列(等长)和质量值,我想根据给定的评分矩阵计算相似度分数。numpy索引与多个阵列

什么是向量化下面的循环最有效的方式:

score = 0 
for i in xrange(len(seq1)): 
    score += similarity[seq1[i], seq2[i], qual1[i], qual2[i]] 

​​是4维float数组,形状=(32,32,100,100); seq1,seq2,qual1qual2是长度相等(1000-40000)的一维int数组。

回答

3

不应该只是工作(tm)?

>>> score = 0 
>>> for i in xrange(len(seq1)): 
     score += similarity[seq1[i], seq2[i], qual1[i], qual2[i]] 
...  
>>> score 
498.71792400493433 
>>> similarity[seq1,seq2, qual1, qual2].sum() 
498.71792400493433 

代码:

import numpy as np 

similarity = np.random.random((32, 32, 100, 100)) 
n = 1000 
seq1, seq2, qual1, qual2 = [np.random.randint(0, s, n) for s in similarity.shape] 

def slow(): 
    score = 0 
    for i in xrange(len(seq1)): 
     score += similarity[seq1[i], seq2[i], qual1[i], qual2[i]] 
    return score 

def fast(): 
    return similarity[seq1, seq2, qual1, qual2].sum() 

给出:

>>> timeit slow() 
100 loops, best of 3: 3.59 ms per loop 
>>> timeit fast() 
10000 loops, best of 3: 143 us per loop 
>>> np.allclose(slow(),fast()) 
True 
+0

那真是太好了。我喜欢这个比我自己的回答更好(尽管我可能只是为了对比而离开我)。 +1。 – 2013-05-02 15:32:56

+0

这是一个我不知道的“numpy”功能。 – GWW 2013-05-02 15:33:47

+0

谢谢! - 在我的机器上的计时(包括John Zwinck的答案为'第三')1000次迭代10000: 慢速:17.1289219856,快速:0.61208987236,第三:15.7027080059 – 2013-05-02 17:05:00

0

这个怎么样?

score = numpy.sum(map(similarity.__getitem__, zip(seq1, seq2, qual1, qual2))) 

当然,你也可以试用itertools imap和izip。因为__getitem__需要一个元组而不是四个数字,所以zip是必要的,也许可以通过在itertools模块的较暗角落查找来改进。