简体   繁体   English

如何检查numpy数组列表是否包含给定的测试数组?

[英]How to check if a list of numpy arrays contains a given test array?

I have a list of numpy arrays, say, 我有一个numpy数组的列表,例如,

a = [np.random.rand(3, 3), np.random.rand(3, 3), np.random.rand(3, 3)]

and I have a test array, say 我有一个测试阵列

b = np.random.rand(3, 3)

I want to check whether a contains b or not. 我想检查a是否包含b However 然而

b in a 

throws the following error: 引发以下错误:

ValueError: The truth value of an array with more than one element is ambiguous. ValueError:具有多个元素的数组的真值不明确。 Use a.any() or a.all() 使用a.any()或a.all()

What is the proper way for what I want? 我想要什么的正确方法是什么?

You can just make one array of shape (3, 3, 3) out of a : 你可以只让形状的一个阵列(3, 3, 3)出的a

a = np.asarray(a)

And then compare it with b (we're comparing floats here, so we should use isclose() ) 然后将其与b比较(我们在这里比较浮点数,因此我们应该使用isclose()

np.all(np.isclose(a, b), axis=(1, 2))

For example: 例如:

a = [np.random.rand(3,3),np.random.rand(3,3),np.random.rand(3,3)]
a = np.asarray(a)
b = a[1, ...]       # set b to some value we know will yield True

np.all(np.isclose(a, b), axis=(1, 2))
# array([False,  True, False])

Ok so in doesn't work because it's effectively doing 好吧in因为它有效

def in_(obj, iterable):
    for elem in iterable:
        if obj == elem:
            return True
    return False

Now, the problem is that for two ndarrays a and b , a == b is an array (try it), not a boolean, so if a == b fails. 现在的问题是,对于两个ndarray aba == b是一个数组(尝试),而不是布尔值,因此if a == b失败。 The solution is do define a new function 解决方案是定义一个新功能

def array_in(arr, list_of_arr):
     for elem in list_of_arr:
        if (arr == elem).all():
            return True
     return False

a = [np.arange(5)] * 3
b = np.ones(5)

array_in(b, a) # --> False

This error is because if a and b are numpy arrays then a == b doesn't return True or False , but array of boolean values after comparing a and b element-wise. 该错误是因为,如果abnumpy arraysa == b不会返回TrueFalse ,而是在a元素比较ab之后返回boolean值的array

You can try something like this: 您可以尝试如下操作:

np.any([np.all(a_s == b) for a_s in a])
  • [np.all(a_s == b) for a_s in a] Here you are creating list of boolean values, iterating through elements of a and checking if all elements in b and particular element of a are the same. [np.all(a_s == b) for a_s in a]这里所创建的列表boolean值,通过的元件迭代a和检查是否在所有的元素b的和特定元件a是相同的。

  • With np.any you can check if any element in your array is True 使用np.any您可以检查数组中的任何元素是否为True

As pointed out in this answer , the documentation states that: 该答案所指出, 文档指出:

For container types such as list, tuple, set, frozenset, dict, or collections.deque, the expression x in y is equivalent to any(x is e or x == e for e in y). 对于列表,元组,集合,frozenset,dict或collections.deque等容器类型,y中的表达式x等于any(x为e或y中的e为x == e)。

a[0]==b is an array, though, containing an element-wise comparison of a[0] and b . a[0]==b是一个数组,其中包含a[0]b逐元素比较。 The overall truth value of this array is obviously ambiguous. 该数组的整体真值显然是不明确的。 Are they the same if all elements match, or if most match of if at least one matches? 如果所有元素都匹配,或者如果至少一个匹配,则大多数匹配,它们是否相同? Therefore, numpy forces you to be explicit in what you mean. 因此, numpy迫使您明确表达自己的意思。 What you want to know, is to test whether all elements are the same. 您想知道的是测试所有元素是否相同。 You can do that by using numpy 's all method: 您可以使用numpyall方法来做到这一点:

any((b is e) or (b == e).all() for e in a)

or put in a function: 或加入一个函数:

def numpy_in(arrayToTest, listOfArrays):
    return any((arrayToTest is e) or (arrayToTest == e).all()
               for e in listOfArrays)

Use array_equal from numpy 使用numpy中的array_equal

    import numpy as np
    a = [np.random.rand(3,3),np.random.rand(3,3),np.random.rand(3,3)]
    b = np.random.rand(3,3)

    for i in a:
        if np.array_equal(b,i):
            print("yes")

As highlighted by @jotasi the truth value is ambiguous due to element-wise comparison within the array. 正如@jotasi所强调的,由于数组中元素之间的比较,真值是不明确的。 There was a previous answer to this question here . 有一个以前这个问题的答案在这里 Overall your task can be done in various ways: 总体而言,您的任务可以通过多种方式完成:

  1. list-to-array: 列出到阵列:

You can use the "in" operator by converting the list to a (3,3,3)-shaped array as follows: 您可以通过将列表转换为(3,3,3)形状的数组来使用“ in”运算符,如下所示:

    >>> a = [np.random.rand(3, 3), np.random.rand(3, 3), np.random.rand(3, 3)]
    >>> a= np.asarray(a)
    >>> b= a[1].copy()
    >>> b in a
    True
  1. np.all: np.all:

     >>> any(np.all((b==a),axis=(1,2))) True 
  2. list-comperhension: This done by iterating over each array: list-comperhension:通过遍历每个数组来完成:

     >>> any([(b == a_s).all() for a_s in a]) True 

Below is a speed comparison of the three approaches above: 下面是上述三种方法的速度比较:

Speed Comparison 速度比较

import numpy as np
import perfplot

perfplot.show(
    setup=lambda n: np.asarray([np.random.rand(3*3).reshape(3,3) for i in range(n)]),
    kernels=[
        lambda a: a[-1] in a,
        lambda a: any(np.all((a[-1]==a),axis=(1,2))),
        lambda a: any([(a[-1] == a_s).all() for a_s in a])
        ],
    labels=[
        'in', 'np.all', 'list_comperhension'
        ],
    n_range=[2**k for k in range(1,20)],
    xlabel='Array size',
    logx=True,
    logy=True,
    )

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM