你如何从numpy数组列表中删除一个numpy数组?

时间:2010-07-01 11:41:48

标签: python numpy

如果我有一个numpy数组列表,那么使用remove方法会返回一个值错误。

例如:

import numpy as np

l = [np.array([1,1,1]),np.array([2,2,2]),np.array([3,3,3])]

l.remove(np.array([2,2,2]))

会给我

  

ValueError:具有多个元素的数组的真值是不明确的。使用a.any()或a.all()

我似乎无法使all()工作,这是不可能的吗?

4 个答案:

答案 0 :(得分:11)

这里的问题是当两个numpy数组与==进行比较时,就像在remove()和index()方法中一样,返回一个布尔值的numpy数组(元素比较的元素),这被解释为暧昧。比较两个numpy数组是否相等的好方法是使用numpy的array_equal()函数。

由于list的remove()方法没有key参数(比如sort()),我认为你需要自己创建函数来执行此操作。这是我做的一个:

def removearray(L,arr):
    ind = 0
    size = len(L)
    while ind != size and not np.array_equal(L[ind],arr):
        ind += 1
    if ind != size:
        L.pop(ind)
    else:
        raise ValueError('array not found in list.')

如果你需要它更快,那么你可以Cython-ize它。

答案 1 :(得分:4)

你走了:

list.pop(1)

更新

list.pop(list.index(element))

我认为你不能遍历列表以找到元素的位置。别担心。默认情况下,Python会使用一个好的搜索算法来为您找到它。

答案 2 :(得分:1)

使用Python基本功能

以下解决方案使用了list.index(element)方法中的 数组列表。

搜索numpy.ndarray必须能够哈希numpy.ndarray实例。因此,我们需要实施 哈希算法。这很简单,尽管给出的代码看起来有些长,但是大多数行用于检查边缘情况或添加注释。

您可以将代码复制粘贴到文件中,然后从命令行运行它 或SDK为PyCharm。

您需要了解

  • []。index(element)
  • 哈希(哈希和哈希冲突)
  • 如何对numpy数组进行哈希处理

注意:

  • 哈希冲突可能导致错误的决定,您需要自行决定 关于概率和影响
  • 如果有多个具有相同数据的数组,则仅删除该数组的第一个匹配项。

import numpy as np


def remove(array, arrays):
    """
    Remove the `array` from the `list` of `arrays`
    Operates inplace on the `list` of `arrays` given

    :param array: `np.ndarray`
    :param arrays: `list:np.ndarray`
    :return: None
    """

    assert isinstance(arrays, list), f'Expected a list, got {type(arrays)} instead'
    assert isinstance(array, np.ndarray), f'Expected a numpy.ndarray, got {type(array)} instead'
    for a in arrays:
        assert isinstance(a, np.ndarray), f'Expected a numpy.ndarray instances in arrays, found {type(a)} instead'

    # Numpy ndarrays are not hashable by default, so we create
    # our own hashing algorithm. The following will do the job ...
    def _hash(a):
        return hash(a.tobytes())

    try:
        # We create a list of hashes and search for the index
        # of the hash of the array we want to remove.
        index = [_hash(a) for a in arrays].index(_hash(array))
    except ValueError as e:
        # It might be, that the array is not in the list at all.
        print(f'Array not in list. Leaving input unchanged.')
    else:
        # Only in the case of no exception we pop the array
        # with the same index/position from the original
        # arrays list
        arrays.pop(index)


if __name__ == '__main__':

    # Let's start with the following arrays as given in the question
    arrays = [np.array([1, 1, 1]), np.array([2, 2, 2]), np.array([3, 3, 3])]
    print(arrays)

    # And remove this array instance from it.
    # Note, this is a new instance, so the object id is
    # different. Structure and values coincide.
    remove(np.array([2, 2, 2]), arrays)

    # Let's check the result
    print(arrays)

    # Let's check, whether our edge case handling works.
    remove(np.array([1, 2, 3]), arrays)

答案 3 :(得分:1)

使用Python和Numpy的基本功能

您可以运行以下一种代码来获取结果...

import numpy as np

# Your inputs ...
l = [np.array([1, 1, 1]), np.array([2, 2, 2]), np.array([3, 3, 3])]
array_to_remove = np.array([2, 2, 2])

# My result ...
result = [a for a, skip in zip(l, [np.allclose(a, array_to_remove) for a in l]) if not skip]

print(result)

...或复制以下内容,并将其粘贴到脚本中并进行一些试验。

您需要

  • numpy.allclose可比较numpy数组直至浮点表示错误
  • zip
  • 列表理解
  • 面具的概念

注意,...

  • 此解决方案返回一个列表,其中不包含我们搜索的数组的所有情况
  • 返回的列表引用了np.ndarray实例,这些实例也从初始列表中引用。没有副本!

import numpy as np


def remove(array, arrays):
    """
    Remove the `array` from the `list` of `arrays`
    Returns list with remaining arrays by keeping the order.

    :param array: `np.ndarray`
    :param arrays: `list:np.ndarray`
    :return: `list:np.ndarray`
    """

    assert isinstance(arrays, list), f'Expected a list, got {type(arrays)} instead'
    assert isinstance(array, np.ndarray), f'Expected a numpy.ndarray, got {type(array)} instead'
    for a in arrays:
        assert isinstance(a, np.ndarray), f'Expected a numpy.ndarray instances in arrays, found {type(a)} instead'

    # We use np.allclose for comparing arrays, this will work even if there are
    # floating point representation differences.
    # The idea is to create a boolean mask of the same lenght as the input arrays.
    # Then we loop over the arrays-elements and the mask-elements and skip the
    # flagged elements
    mask = [np.allclose(a, array) for a in arrays]
    return [a for a, skip in zip(arrays, mask) if not skip]


if __name__ == '__main__':

    # Let's start with the following arrays as given in the question
    arrays = [np.array([1, 1, 1]), np.array([2, 2, 2]), np.array([3, 3, 3])]
    print(arrays)

    # And remove this array instance from it.
    # Note, this is a new instance, so the object id is
    # different. Structure and values coincide.
    _arrays = remove(np.array([2, 2, 2]), arrays)

    # Let's check the result
    print(_arrays)

    # Let's check, whether our edge case handling works.
    print(arrays)
    _arrays = remove(np.array([1, 2, 3]), arrays)
    print(_arrays)