在2个单独的numpy数组中查找匹配点

时间:2015-04-08 16:04:00

标签: python arrays performance numpy compare

我有两个不同大小的数组,包含3d点。我想有效地比较两个数组并找到匹配的点,并最终返回一个简单数量的匹配点。

pA=[[0,0,0],[0,1,0],[1,2,4],[10,3,4],[1,20,1],[5,3,2]]
pB=[[14,1,0],[1,2,4],[1,20,1],[15,1,0]]

#returns 2

目前我有一个草率循环可以解决这个问题,但它不是非常友好,这是一个问题,因为我试图匹配许多具有更多点数的数组

t= np.array([pA[x]==pB for x in range(len(pA))]).sum(2)
print np.sum(t==3)

我只是不确定如何有效地比较两个不同大小的多维数组。然后如何为大量对进行多次迭代。

修改

找到了一个非常快的解决方法,它结合了数组,创建了一个独特的数组版本,然后比较了两个数组的长度。

pts=np.concatenate((pA,pB),axis=0)
pts2 = np.unique(pts.view([('', pts.dtype)]*pts.shape[1]))
return len(pts)-len(pts2)

2 个答案:

答案 0 :(得分:3)

不知道这对您的完整数据集有何影响,但尝试使用Scipy的kdtree:

from scipy.spatial import cKDTree

pA=[[0,0,0],[0,1,0],[1,2,4],[10,3,4],[1,20,1],[5,3,2]]
pB=[[14,1,0],[1,2,4],[1,20,1],[15,1,0]]

kdtree = cKDTree(pA)
dists, inds = kdtree.query(pB, distance_upper_bound=1e-5)
result = (dists == 0).sum()

答案 1 :(得分:1)

这是一种仅使用numpy操作的方法。这里的基本思想是我们将这两个列表连接成一个numpy数组。然后,我们按行排序以将匹配点带到连续的行。接下来,我们执行diff以获得匹配的所有零行,np.all(...==0,1) 拾取。我们计算所有这些事件,以便为我们提供这两个列表之间匹配点数的所需输出。

下面列出了实施 -

import numpy as np

# Inputs
pA=[[0,0,0],[0,1,0],[1,2,4],[10,3,4],[1,20,1],[5,3,2]]
pB=[[14,1,0],[1,2,4],[1,20,1],[15,1,0]]

# Form concatenate array of pA and pB
pts = np.concatenate((pA,pB),axis=0)

# Sort pts by rows
spts = pts[pts[:,1].argsort(),]

# Finally get counts by DIFFing along rows and counting all zero rows
counts = np.sum(np.diff(np.all(np.diff(spts,axis=0)==0,1)+0)==1)

输出 -

In [152]: counts
Out[152]: 2

即使您在任一列表中有重复点,上述代码仍然有效。所以,让我们在早期代码的输入中添加一些重复点 -

# Inputs
pA=[[0,0,0],[0,1,0],[1,2,4],[10,3,4],[1,20,1],[5,3,2],[1,2,4]]
pB=[[14,1,0],[1,2,4],[1,20,1],[15,1,0],[1,2,4]]

使用修改后的输入运行代码后,输出仍保持为2,这是预期的输出。

如果您确定其中任何一个列表中没有重复条目,您可以使用简化版本替换最后一步 -

counts = np.sum(np.all(np.diff(spts,axis=0)==0,1))