比较数组,找到相同的元素并返回索引

时间:2017-05-26 23:09:57

标签: python numpy

我有两个numpy数组(长度不同)

第一个是(n)喜欢:

a = [0, 1, 2, 5, 6, 7]

第二个是(n,3),如:

b = [[0, 1, 3],[8, 3, 9],[9, 8, 4],[0, 4, 5],[1, 7, 3],[1, 5, 7],[2, 3, 7],[4, 2, 6],[5, 4, 6],[5, 6, 7]]

现在我想检查第二个数组的每一列是否包含第一个数组中的一个数字,并在可能的情况下返回该列的索引。

b[0] -> [0, 1, 3] contains 0 and 1 so I need that index (only once)
b[1] -> [8, 3, 9] does not contain any of the numbers from a, so I don't need that index

结果shell是一个包含所有索引的数组,在本例中如下:

indexes = [0, 3, 4, 5....]

有没有办法检查?处理速度不是问题!

5 个答案:

答案 0 :(得分:1)

您可以使用np.in1d获取匹配的掩码。现在,np.in1d在处理之前展平输入。因此,我们需要在之后重新调整为2D,然后检查每行中的任何一个匹配项,并获取np.flatnonzero的行索引。

因此,实施将是 -

np.flatnonzero(np.in1d(b,a).reshape(b.shape).any(1))

使用给定样本的中间和最终输出运行样本 -

In [143]: a
Out[143]: array([0, 1, 2, 5, 6, 7])

In [144]: b
Out[144]: 
array([[0, 1, 3],
       [8, 3, 9],
       [9, 8, 4],
       [0, 4, 5],
       [1, 7, 3],
       [1, 5, 7],
       [2, 3, 7],
       [4, 2, 6],
       [5, 4, 6],
       [5, 6, 7]])

In [145]: np.in1d(b,a).reshape(b.shape)
Out[145]: 
array([[ True,  True, False],
       [False, False, False],
       [False, False, False],
       [ True, False,  True],
       [ True,  True, False],
       [ True,  True,  True],
       [ True, False,  True],
       [False,  True,  True],
       [ True, False,  True],
       [ True,  True,  True]], dtype=bool)

In [146]: np.in1d(b,a).reshape(b.shape).any(1)
Out[146]: array([ True, False, False,  True,  True, 
                    True,  True,  True,  True,  True], dtype=bool)

In [147]: np.flatnonzero(np.in1d(b,a).reshape(b.shape).any(1))
Out[147]: array([0, 3, 4, 5, 6, 7, 8, 9])

答案 1 :(得分:1)

列表 b 应理解为一个矩阵,其中的子列表是,而不是

话虽如此,考虑到你提供的例子,我假设你真正想做的是找到b行中的匹配。然后我们将按如下方式进行:

  1. 检查 a 中的任何数字是否与 b 的指定子列表中包含的数字相匹配。

  2. 获取一个数组,其元素是标识 b 的子列表的索引,这些子列表至少包含 a 之一。

  3. 我会使用标准的Python 3 sintax。然后,我会使用numpy asarray 函数将其转换为数组:

    import numpy as np
    def matches(a,b):
    list = [] 
    for i in range(len(b)):
        for j in range(len(b[0])):
            if b[i][j] in a:
                list = list+[i]
                break
            else:
                 pass
    arrayIndexes = np.asarray(list)
    return arrayIndexes
    
    print(matches([0,1,2,5,6,7],
             [[0,1,3],
              [8,3,9],
              [9,8,4],
              [0,4,5],
              [1,7,3],
              [1,5,7],
              [2,3,7],
              [4,2,6],
              [5,4,6],
              [5,6,7]]))
    

    带索引的返回numpy数组将是名为 arrayIndexes 的对象,并包含以下内容:

    array([0,3,4,5,6,7,8,9])
    

答案 2 :(得分:0)

使用in1d

a = [0, 1, 2, 5, 6, 7]
b = [[0, 1, 3],[8, 3, 9],[9, 8, 4],[0, 4, 5],[1, 7, 3],[1, 5, 7],[2, 3, 7],[4, 2, 6],[5, 4, 6],[5, 6, 7]]
a, b = map(np.array, (a, b))
np.where(np.in1d(b, a).reshape(b.shape).any(axis=1))[0]

答案 3 :(得分:0)

通过简单(但可能很大)的广播比较:

In [14]: mask=a==b[:,:,None]
In [15]: mask.shape
Out[15]: (10, 3, 6)
In [16]: mask.any(axis=2)    # any match over elements of a
Out[16]: 
array([[ True,  True, False],
       [False, False, False],
       [False, False, False],
       [ True, False,  True],
       [ True,  True, False],
       [ True,  True,  True],
       [ True, False,  True],
       [False,  True,  True],
       [ True, False,  True],
       [ True,  True,  True]], dtype=bool)
In [17]: mask.any(axis=2).any(axis=1)   # and match on any colum
Out[17]: array([ True, False, False,  True,  True,  True,  True,  True,  True,  True], dtype=bool)
In [18]: np.where(mask.any(axis=2).any(axis=1))
Out[18]: (array([0, 3, 4, 5, 6, 7, 8, 9], dtype=int32),)

in1d有几种模式,具体取决于2个输入的相对大小,但我认为其中有一种模式相同。

In [26]: timeit np.where(np.any(a==b[:,:,None], axis=(1,2)))[0]
The slowest run took 4.19 times longer than the fastest. This could mean that an intermediate result is being cached.
100000 loops, best of 3: 18.3 µs per loop
In [27]: timeit np.flatnonzero(np.in1d(b,a).reshape(b.shape).any(1))
10000 loops, best of 3: 38.2 µs per loop

答案 4 :(得分:0)

您只需使用list comprehension并使用any()就可以完成此操作:

a = [0, 1, 2, 5, 6, 7]
b = [[0, 1, 3],[8, 3, 9],[9, 8, 4],[0, 4, 5],[1, 7, 3],[1, 5, 7],[2, 3, 7],[4, 2, 6],[5, 4, 6],[5, 6, 7]]

final = [k for k in range(len(b)) if any(j in b[k] for j in a)]
print(final)

输出:

[0, 3, 4, 5, 6, 7, 8, 9]