如何匹配两个numpy数组中包含的值对

时间:2019-02-22 13:19:11

标签: python numpy coordinates numpy-ndarray

我有两组坐标,想找出coo组中的哪些坐标与targets组中的任何坐标相同。我想知道coo集中的索引,这意味着我想获取索引列表或布尔值。

import numpy as np

coo = np.array([[1,2],[1,6],[5,3],[3,6]]) # coordinates
targets = np.array([[5,3],[1,6]]) # coordinates of targets

print(np.isin(coo,targets))

[[ True False]
 [ True  True]
 [ True  True]
 [ True  True]]

期望的结果将是以下两个之一:

[False True True False] # bool list
[1,2] # list of concerning indices

我的问题是...

  • np.isin没有axis属性,因此我可以使用axis=1
  • 即使对输出的每一行应用 logical和,对于最后一个元素也会返回True,这是错误的。

我知道循环和条件,但是我确信Python具备了更优雅的解决方案的方法。

4 个答案:

答案 0 :(得分:9)

这是利用Search plug-in development的一种方式:

(coo[:,None] == targets).all(2).any(1)
# array([False,  True,  True, False])

详细信息

通过在coo中添加第一个轴的直接比较,检查target中的每一行是否与coo中的每一行相匹配,以便可以针对targets进行广播:

(coo[:,None] == targets)

array([[[False, False],
        [ True, False]],

       [[False, False],
        [ True,  True]],

       [[ True,  True],
        [False, False]],

       [[False, False],
        [False,  True]]])

然后检查第二个轴上哪个ndarrays具有True的{​​{3}}值:

(coo[:,None] == targets).all(2)

array([[False, False],
       [False,  True],
       [ True, False],
       [False, False]])

最后使用broadcasting检查哪些行至少具有一个True

答案 1 :(得分:1)

numpy_indexed软件包以矢量化方式实现了这种类型的功能(免责声明:我是它的作者)。遗憾的是,numpy缺少许多现成的功能;我开始将numpy_indexed合并到numpy中,但是有一些向后兼容的问题,并且像这样的大软件包趋向于缓慢移动。因此在最近三年中没有发生过这种情况;但是python封装生态系统如今运作良好,以至于向您的环境中再添加一个软件包确实非常简单。

require.main

这将具有类似于@fountainhead发布的解决方案的时间复杂度(根据当前接受的答案,对数而不是线性),而且npi库将为您提供自动化测试的安全性,并且许多其他方便的选择,如果您决定从稍微不同的角度来解决这个问题。

答案 2 :(得分:0)

这是一个简单直观的解决方案,实际上使用numpy.isin()匹配元组,而不是匹配单个数字:

# View as a 1d array of tuples
coo_view     = coo.view(dtype='i,i').reshape((-1,))
targets_view = targets.view(dtype='i,i').reshape((-1,))

result = np.isin(coo_view, targets_view)
print (result)
print(result.nonzero()[0])

输出:

[False  True  True False]
[1 2]

注释:

  1. 创建这些views并不涉及任何数据复制。
  2. dtype='i,i'指定我们希望视图的每个元素都是两个整数的元组

答案 3 :(得分:-1)

从@yatu的答案中使用allany方法,我尝试了一些嵌套列表理解。尽管广播明显更干净。

np.array([[x==y for x in coo] for y in targets]).all(2).any(axis=0)

返回:

array([False, True, True, False])