【问题标题】:Find common elements in subarrays of arrays在数组的子数组中查找公共元素
【发布时间】:2018-11-19 06:34:03
【问题描述】:

我有两个形状为 arr1=(~140000, 3) 和 arr2=(~450000, 10) 的 numpy 数组。对于两个数组,每行的前 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], ...]

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

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 for el in arr2 if el[0]==i[0]) .这个速度有点操作,但还是很慢。

你能帮我解决这个问题吗?

【问题讨论】:

  • 您能否提供一些示例输入以及您的预期结果?!更容易提供帮助。
  • 我加了一个例子,你可以看看。
  • 您可以像stackoverflow.com/a/53062049/4045774 一样执行此操作,但您使用 arr2[:,0:3] 创建树并检查 arr1。如果 arr2 中的点不完全一致,但在相同的小公差范围内,这也是有益的。

标签: arrays numpy numpy-ndarray


【解决方案1】:

方法#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.searchsorted(也使用np.unique)的最后改进,我们可以改用argsort -

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

【讨论】:

    【解决方案2】:

    您可以在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]]
    

    【讨论】:

    • 输出应该是 arr2 的行(附加到列表)以及所有其他信息,而不仅仅是坐标。由于 arr1 是 arr2 的子组(感兴趣的坐标),所以这样做没有意义。
    • 感谢您的努力,但它不适用于此。它返回它找到“i”中存在的甚至 1 个值的所有行(因此其他 2 个是错误的)。
    【解决方案3】:

    对于整数 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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-07-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-03-04
      相关资源
      最近更新 更多