在数组的子数组中查找公共元素

时间:2018-11-19 06:34:03

标签: arrays numpy numpy-ndarray

我有两个numpy数组,形状为arr1 =(〜140000,3)和arr2 =(〜450000,10)。对于两个数组,每行的前3个元素都是坐标(z,y,x)。我想查找具有与arr1相同的坐标的arr2行(可以将其视为arr2的子组)。

例如:

arr1 = [[1,2,3],[1,2,5],[1,7,8],[5,6,7]]

arr2 = [[1,2,3,7,66,4,3,44,8,9],[1,3,9,6,7,8,3,4,5,2],[1,5,8,68,7,8,13,4,53,2],[5,6,7,6,67,8,63,4,5,20], ...]

我想找到共同的坐标(与前三个元素相同):

list_arr = [[1,2,3,7,66,4,3,44,8,9], [5,6,7,6,67,8,63,4,5,20], ...]

此刻我正在执行此双循环,这非常慢:

list_arr=[]
for i in arr1:
    for j in arr2:
        if i[0]==j[0] and i[1]==j[1] and i[2]==j[2]:
            list_arr.append (j)

我还尝试创建(在第一个循环之后)arr2的子数组,将其过滤为i [0]的值(arr2_filt = [如果el [0] == i [0]则为arr2中的el的el) 。这个速度有点操作,但是仍然很慢。

您能帮我吗?

3 个答案:

答案 0 :(得分:3)

方法1

这里是views的矢量化对象-

# https://stackoverflow.com/a/45313353/ @Divakar
def view1D(a, b): # a, b are arrays
    a = np.ascontiguousarray(a)
    b = np.ascontiguousarray(b)
    void_dt = np.dtype((np.void, a.dtype.itemsize * a.shape[1]))
    return a.view(void_dt).ravel(),  b.view(void_dt).ravel()

a,b = view1D(arr1,arr2[:,:3])
out = arr2[np.in1d(b,a)]

方法2

另一个带有dimensionality-reduction的整数-

d = np.maximum(arr2[:,:3].max(0),arr1.max(0))
s = np.r_[1,d[:-1].cumprod()]
a,b = arr1.dot(s),arr2[:,:3].dot(s)
out = arr2[np.in1d(b,a)]

改进#1

对于先前列出的两种方法,我们可以使用np.searchsorted代替np.in1d-

unq_a = np.unique(a)
idx = np.searchsorted(unq_a,b)
idx[idx==len(a)] = 0
out = arr2[unq_a[idx] == b]

改进#2

对于使用np.searchsortednp.unique的最后一项改进,我们可以改用argsort-

sidx = a.argsort()
idx = np.searchsorted(a,b,sorter=sidx)
idx[idx==len(a)] = 0
out = arr2[a[sidx[idx]]==b]

答案 1 :(得分:1)

您可以在set的帮助下完成

arr = np.array([[1,2,3],[4,5,6],[7,8,9]])
arr2 = np.array([[7,8,9,11,14,34],[23,12,11,10,12,13],[1,2,3,4,5,6]])

# create array from arr2 with only first 3 columns
temp = [i[:3] for i in arr2]

aset = set([tuple(x) for x in arr])
bset = set([tuple(x) for x in temp])
np.array([x for x in aset & bset])

输出

array([[7, 8, 9],
       [1, 2, 3]])

修改

使用list comprehension

l = [list(i) for i in arr2 if i[:3] in arr]

print(l)

输出:

[[7, 8, 9, 11, 14, 34], [1, 2, 3, 4, 5, 6]]

答案 2 :(得分:0)

对于整数,Divakar已经给出了一个很好的答案。如果要比较浮点数,则必须考虑以下:

1.+1e-15==1.
False
1.+1e-16==1.
True

如果这种行为可能导致您的代码出现问题,我建议执行最近邻居搜索,并可能检查距离是否在指定的阈值内。

import numpy as np
from scipy import spatial
def get_indices_of_nearest_neighbours(arr1,arr2):
  tree=spatial.cKDTree(arr2[:,0:3])
  #You can check here if the distance is small enough and otherwise raise an error
  dist,ind=tree.query(arr1, k=1)
  return ind