【问题标题】:NumPy: Comparing Elements in Two ArraysNumPy:比较两个数组中的元素
【发布时间】:2009-10-23 12:57:26
【问题描述】:

有人遇到过这个问题吗?假设您有两个数组,如下所示

a = array([1,2,3,4,5,6])
b = array([1,4,5])

有没有办法比较 a 中的哪些元素存在于 b 中?例如,

c = a == b # Wishful example here
print c
array([1,4,5])
# Or even better
array([True, False, False, True, True, False])

我试图避免循环,因为它需要数百万个元素。有任何想法吗?

干杯

【问题讨论】:

  • 数组中有哪些数据?类似于示例的类似索引的唯一整数?

标签: python numpy


【解决方案1】:

实际上,有一个比这些更简单的解决方案:

import numpy as np

a = array([1,2,3,4,5,6])
b = array([1,4,5])

c = np.in1d(a,b)

然后得到的 c 是:

array([ True, False, False,  True,  True, False], dtype=bool)

【讨论】:

  • 这个有“几乎相等”的版本吗?在哪里可以指定用于测试相等性的条件?
  • 现在已弃用。 NumPy 文档指出“我们建议在新代码中使用 isin 而不是 in1d。”
【解决方案2】:

使用 np.intersect1d。

#!/usr/bin/env python
import numpy as np
a = np.array([1,2,3,4,5,6])
b = np.array([1,4,5])
c=np.intersect1d(a,b)
print(c)
# [1 4 5]

请注意,如果 a 或 b 具有非唯一元素,则 np.intersect1d 会给出错误答案。在这种情况下使用 np.intersect1d_nu.

还有 np.setdiff1d、setxor1d、setmember1d 和 union1d。看 Numpy Example List With Doc

【讨论】:

    【解决方案3】:

    感谢您的回复 kaizer.se。这不是我想要的,但是根据朋友的建议和你所说的,我想出了以下内容。

    import numpy as np
    
    a = np.array([1,4,5]).astype(np.float32)
    b = np.arange(10).astype(np.float32)
    
    # Assigning matching values from a in b as np.nan
    b[b.searchsorted(a)] = np.nan
    
    # Now generating Boolean arrays
    match = np.isnan(b)
    nonmatch = match == False
    

    这是一个有点麻烦的过程,但它胜过编写循环或使用带有循环的编织。

    干杯

    【讨论】:

    • 这种方法的问题在于,即使a 中的值在b 中不存在(以及其他情况下的重复索引),它也会返回索引。例如:numpy.searchsorted([1, 2], [1.2, 1.3]) 返回的[1, 1] 不适合 OP。
    【解决方案4】:

    Numpy 有一个集合函数 numpy.setmember1d() ,它适用于排序和唯一的数组,并准确返回您想要的布尔数组。如果输入数组不符合条件,您需要转换为设置的格式并反转结果的转换。

    import numpy as np
    a = np.array([6,1,2,3,4,5,6])
    b = np.array([1,4,5])
    
    # convert to the uniqued form
    a_set, a_inv = np.unique1d(a, return_inverse=True)
    b_set = np.unique1d(b)
    # calculate matching elements
    matches = np.setmea_set, b_set)
    # invert the transformation
    result = matches[a_inv]
    print(result)
    # [False  True False False  True  True False]
    

    编辑: 不幸的是,numpy 中的 setmember1d 方法确实效率低下。您提出的 search sorted and assign 方法工作得更快,但是如果您可以直接分配,您还不如直接分配给结果并避免大量不必要的复制。如果 b 包含不在 a 中的任何内容,您的方法也会失败。以下内容更正了这些错误:

    result = np.zeros(a.shape, dtype=np.bool)
    idxs = a.searchsorted(b)
    idxs = idxs[np.where(idxs < a.shape[0])] # Filter out out of range values
    idxs = idxs[np.where(a[idxs] == b)] # Filter out where there isn't an actual match
    result[idxs] = True
    print(result)
    

    我的基准测试显示,您的方法为 91us 与 6.6ms,而 numpy setmember1d 在 1M 元素 a 和 100 个元素 b 上为 109ms。

    【讨论】:

    • 这是一个不错的解决方案。我会尝试你的建议和我刚刚写的内容,看看什么速度更快。非常感谢大家的帮助!
    • 我写的方法快一点。对于 10000 个元素的数组,在 iPython 中使用 timeit 所花费的时间大约为 3 µs。 setmember1d 方法耗时 3 毫秒。我认为你的方法更优雅,但我需要速度。
    • 您忘记在第 3 行关闭括号。你应该在一些计算机科学教授注意到它之前修复它......
    • ebresert:看来你是对的,setmember1d 在 numpy 中有一个绝对糟糕的实现。但是您使用的方法似乎无缘无故地使用了 nan 值,您不妨直接使用结果数组。我将使用相应的示例进行编辑。
    • Ants Aasma:你的编辑很好。我在我的代码中实现了它的一部分并再次提高了速度。我没有做 nans,而是输入 -1,然后在 match = b >= 0 上进行过滤。在我的情况下,我正在处理索引,因此没有 -1 的索引。这就是我使用 np.nan 的原因,它适用于更一般的情况。感谢您的输入。我的代码现在真的飞起来了。
    【解决方案5】:

    ebresset, your answer 将不起作用,除非 a 是 b 的子集(并且 a 和 b 已排序)。否则 searchsorted 将返回错误索引。我必须做类似的事情,并将其与您的代码结合起来:

    # Assume a and b are sorted
    idxs = numpy.mod(b.searchsorted(a),len(b))
    idxs = idxs[b[idxs]==a]
    b[idxs] = numpy.nan
    match = numpy.isnan(b)
    

    【讨论】:

      【解决方案6】:

      您的示例暗示了类似集合的行为,更关心数组中的存在,而不是在正确的位置放置正确的元素。 Numpy 用它的数学数组和矩阵做这不同的事情,它只会告诉你关于正确位置的项目。你能做到吗?

      >>> import numpy
      >>> a = numpy.array([1,2,3])
      >>> b = numpy.array([1,3,3])
      >>> a == b
      array([ True, False,  True], dtype=bool)
      

      【讨论】:

      • 对不起,这个例子你试试不行;此外,您必须先对数组进行排序。
      • @dalloligom:嗯,我从我的交互式会话中复制过来,所以至少它与某些版本的 Python 和 Numpy 完全一样。
      • 好的,但是如果两个数组的长度不同就不行了;无论如何,您必须先对它们进行排序(尝试数组([1,2,3])==数组([2,3,1])。他想知道一个数组的哪些元素存在于另一个数组中。跨度>
      • 顺便说一下,即使对数组进行排序也不起作用……您必须使用集合结构。
      • @dallologm:你看我的回答了吗?好像我没听懂?
      猜你喜欢
      • 2012-05-21
      • 2019-01-13
      • 1970-01-01
      • 2016-06-19
      • 2017-01-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多