【问题标题】:NumPy check if 2D array is subset of 2D array [duplicate]NumPy检查二维数组是否是二维数组的子集[重复]
【发布时间】:2016-09-12 16:52:04
【问题描述】:

我想检查数组b 是否是数组a 的子集。子集是指我想检查b 的所有元素是否都在a 中找到。

这是我的代码:

import numpy as np
a = np.array([[1,7,9],[8,3,12],[101,-74,0.5]])
b = np.array([[1,9],[8,12],[101,0.5]])
print a
print b

这是输出

数组一个

[[   1.     7.     9. ]
 [   8.     3.    12. ]
 [ 101.   -74.     0.5]]

数组 b

[[   1.     9. ]
 [   8.    12. ]
 [ 101.     0.5]]

有没有办法检查 b 是否是 a 的子集?

编辑:附加信息:

根据下面的 cmets,我应该澄清我需要知道数组 b 是否是数组 a 的子集 - 如果子集中甚至缺少一个元素,那么我正在寻找一种方法来检查这一点。我不需要指示该元素在子集中的哪个位置丢失,而只是知道它丢失了。如果可以提供有关缺失元素的其他信息,那么这将是一个奖励,但这不是硬性要求。很抱歉没有早点解决这个问题。

我将问题表述为子集的原因是,如果一个数组是另一个数组的子集,那么这对我来说意味着子集数组的所有值都存在于更大的数组中。

【问题讨论】:

  • 我认为您需要详细说明“我想检查是否在 a 中找到 b 的所有元素”,因为我们在这里处理 2D 数组。想想可能否定你对“子集”定义的各种情况,想想必须遵循的其他情况。来自ab 的相应行的所有元素?仅在b 中沿同一列?
  • 对不起,我应该解释一下。检查b 各列中的所有元素是否是a 中的子集。这就是我所追求的。
  • 所以在这种情况下所需的输出将是一个具有三个 true 值的 bool 数组,对吗?每行一个,其中确实有作为子集的列。
  • 你如何在这里定义子集?您是否正在寻找一对布尔掩码的存在,例如 (a[m1,m2] == b).all(),即行和列的某个子集

标签: python arrays python-2.7 numpy


【解决方案1】:

我想你想要numpy.in1d,像这样:

import numpy as np
a = np.array([[1,7,9],[8,3,12],[101,-74,0.5]])
b = np.array([[1,9],[8,12],[101,0.5]])

np.in1d(b.ravel(), a.ravel()).all()

【讨论】:

  • 非常感谢。尽管我接受了较早的答案,但这也有效。简单的单线。
【解决方案2】:

这应该可行:

set(np.unique(b)).issubset(set(np.unique(a)))

编辑:上面的代码返回 TrueFalse 而不是布尔值的列向量。从@Eelco Hoogendoorn 对您的问题的评论中,我了解到您实际上有兴趣检查b 是否是a 的相应 的子集, 正确的?假设这是正确的问题描述,以下单行应该可以工作:

np.array([[set(bi).issubset(set(ai))] for ai, bi in zip(map(tuple, a), map(tuple, b))])

上面的代码简单易读,不需要第三方依赖。诚然,这是一个快速而肮脏的解决方案,因为正如@Bi Rico 正确指出的那样,这种方法可能非常低效。如果您需要处理大型数组,您应该坚持使用矢量化算法。

【讨论】:

  • 谢谢。这有效,它回答了我的问题。
  • 值得注意的是,对于较大的数组,在 numpy 数组和内置类型(如集合和列表)之间切换在处理时间和内存使用方面可能会非常昂贵。
  • 如果我正确阅读了您的问题,这不会回答它;它同时考虑数组中的所有元素,并且不按列执行。
  • 感谢您的反馈。任何一个选项都对我有用。我只是想检查是否存在 False - 这表明一个值(任何值)是不同的。如果是这种情况,那么我知道一个数组有问题。如果可以在行之间进行比较,就像您在编辑中所做的那样,那么这也是有用的,但不是必需的。您最初的答案工作得很好,因为它识别出 False 或 True,而这正是我正在寻找的。感谢您添加的解决方案。
【解决方案3】:

如果要比较,一种方法是先将它们分组:

a = np.array([[1,7,9],[8,3,12],[101,-74,0.5]])
b = np.array([[1,9],[8,12],[101,0.5]])
c = np.array([[1,9],[8,12],[101,-74.]])

def bycols(arr):
    tr=arr.T.copy()
    type=np.dtype((np.void,tr.strides[0]))
    return tr.view(type).squeeze()

A,B,C=[bycols(x) for x in (a,b,c)]    

那么 A,B,C 只是表示列的字节数组:

In [5]: [x.shape for x in (A,B,C)]
Out[5]: [(3,), (2,), (2,)]

您现在可以使用 np.in1d 测试归属:

In [6]: np.in1d(C,A)
Out[6]: array([ True, False], dtype=bool)

In [7]: np.in1d(B,A)
Out[7]: array([ True,  True], dtype=bool)

但是:

In [8]: np.in1d(c,a)
Out[8]: array([ True,  True,  True,  True,  True,  True], dtype=bool)

因为 np1d 适用于扁平数组。

【讨论】:

    【解决方案4】:

    如果我正确阅读了您的问题(测试 a 和 b 中的每个相应行,如果 b 中的行是 a 中的行的子集),则应该有效且正确地做到这一点:

    import numpy_indexed as npi
    rowsa = np.indices(a.shape)[0]
    rowsb = np.indices(b.shape)[0]
    # test for each value-rowidx pair in b if it is contained in a
    c = npi.contains((a.flatten(), rowsa.flatten()), (b.flatten(), rowsb.flatten()))
    # check that all elements on a row are contained
    row_is_subset = c.reshape(b.shape).all(axis=1)
    

    您需要安装numpy_indexed 包(免责声明:我是它的作者)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-02-25
      • 1970-01-01
      • 2018-04-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多