【问题标题】:Check how many numpy array within a numpy array are equal to other numpy arrays within another numpy array of different size检查一个numpy数组中有多少个numpy数组等于另一个不同大小的numpy数组中的其他numpy数组
【发布时间】:2017-08-29 10:00:24
【问题描述】:

我的问题

假设我有

a = np.array([ np.array([1,2]), np.array([3,4]), np.array([5,6]), np.array([7,8]), np.array([9,10])])
b = np.array([ np.array([5,6]), np.array([1,2]), np.array([3,192])])

它们是两个大小不同的数组,包含其他数组(内部数组大小相同!)

我想计算 a 中有多少 b 项(即内部数组)。请注意,我没有考虑他们的立场!

我该怎么做?

我的尝试

count = 0
for bitem in b:
     for aitem in a:
         if aitem==bitem:
               count+=1

有没有更好的方法?尤其是在一行中,也许有点理解..

【问题讨论】:

  • 只为标题投票
  • @thanks man,感激不尽

标签: python arrays numpy


【解决方案1】:

numpy_indexed 包包含针对这些类型问题的高效(通常为 nlogn)和矢量化解决方案:

import numpy_indexed as npi
count = len(npi.intersection(a, b))

请注意,这与您的双循环略有不同,例如丢弃 a 和 b 中的重复条目。如果您想在 b 中保留重复项,则可以这样做:

count = npi.in_(b, a).sum()

a 中的重复条目也可以通过执行 npi.count(a) 并考虑其结果来处理;但无论如何,我只是为了说明目的而胡言乱语,因为我认为这种区别对你来说可能并不重要。

【讨论】:

  • 你认为这两种解决方案比上面描述的更快吗?
  • 这些方法在内存和计算上都是二次的;所以除了几个数组元素之外,绝对是
【解决方案2】:

这是一个简单的方法:

a = np.array([ np.array([1,2]), np.array([3,4]), np.array([5,6]), np.array([7,8]), np.array([9,10])])
b = np.array([ np.array([5,6]), np.array([1,2]), np.array([3,192])])

count = np.count_nonzero(
    np.any(np.all(a[:, np.newaxis, :] == b[np.newaxis, :, :], axis=-1), axis=0))

print(count)
>>> 2

【讨论】:

  • 首先,count 不应该是 2 吗?输入中只有 2 个匹配的数组。您正在计算匹配元素(5、6、1、2 和 3)而不是匹配数组((5,6)和(1,2))
  • 另外,np.logical_or.reduce(.., axis = 0) 等价于np.any( . . ., axis = 0),与简单的sum() 相比,在布尔数组上使用np.count_nonzero 是一种浪费
  • @DanielF 你是对的,我误读了这个问题,我认为这是关于一般元素,而不是子数组。 count_nonzero 比这里的 sum 快得多(在 IPython 中检查 %timeit (np.random.rand(10000000) > .5).sum()%timeit np.count_nonzero(np.random.rand(10000000) > .5))。
【解决方案3】:

你可以在一个班轮中做你想做的事情,如下所示:

count = sum([np.array_equal(x,y) for x,y in product(a,b)])

说明

下面是对发生的事情的解释:

  1. 使用itertools.product 遍历两个数组,这将在两个数组的笛卡尔积上创建一个迭代器。
  2. 使用np.array_equal比较来自步骤1.的元组(x,y)中的每两个数组
  3. 在列表上使用 sum 时,True 等于 1

完整示例:

最终代码如下所示:

import numpy as np 
from itertools import product 
a = np.array([ np.array([1,2]), np.array([3,4]), np.array([5,6]), np.array([7,8]), np.array([9,10])])
b = np.array([ np.array([5,6]), np.array([1,2]), np.array([3,192])])
count = sum([np.array_equal(x,y) for x,y in product(a,b)])
# output: 2

【讨论】:

    【解决方案4】:

    您可以将行转换为dtype = np.void,然后在生成的一维数组上使用np.in1d

    def void_arr(a):
        return np.ascontiguousarray(a).view(np.dtype((np.void, a.dtype.itemsize * a.shape[1]))) 
    
    b[np.in1d(void_arr(b), void_arr(a))]
    
    array([[5, 6],
           [1, 2]])
    

    如果你只想要交叉点的数量,那就是

    np.in1d(void_arr(b), void_arr(a)).sum()
    
    2
    

    注意:如果ba中有重复项,则np.in1d(void_arr(b), void_arr(a)).sum()可能不等于np.in1d(void_arr(a), void_arr(b)).sum()。我已将原始答案的顺序颠倒以匹配您的问题(即b 中有多少元素在a 中?)

    更多信息见第三个回答here

    【讨论】:

      猜你喜欢
      • 2020-12-21
      • 2011-07-27
      • 2017-12-27
      • 2012-04-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-12-17
      相关资源
      最近更新 更多