有没有办法在python中删除numpy数组“就地”的特定元素:

时间:2016-11-04 15:43:24

标签: python arrays numpy

当调用“np.delete()”时,我不想为缩小尺寸的数组定义一个新变量。我想在原始的numpy数组上执行delete。任何想法?

>>> arr = np.array([[1,2], [5,6], [9,10]])
>>> arr
array([[ 1,  2],
       [ 5,  6],
       [ 9, 10]])
>>> np.delete(arr, 1, 0)
array([[ 1,  2],
       [ 9, 10]])
>>> arr
array([[ 1,  2],
       [ 5,  6],
       [ 9, 10]])
but I want:
>>> arr
array([[ 1,  2],
       [ 9, 10]])

5 个答案:

答案 0 :(得分:2)

NumPy数组是固定大小的,因此不能有np.delete的就地版本。任何这样的函数都必须改变数组的大小。

最接近的是重新分配arr变量:

arr = numpy.delete(arr, 1, 0)

答案 1 :(得分:1)

delete调用不会修改原始数组,它会复制它并在删除完成后返回副本。

>>> arr1 = np.array([[1,2], [5,6], [9,10]])
>>> arr2 = np.delete(arr, 1, 0)
>>> arr1
array([[ 1,  2],
   [ 5,  6],
   [ 9, 10]])
>>> arr2 
array([[ 1,  2],
   [ 9, 10]])

答案 2 :(得分:1)

如果是性能问题,您可能需要尝试(但测试它,因为我不确定)创建视图*而不是使用np.delete。您可以通过切片来实现,该切片应该是 inplace 操作:

import numpy as np

arr = np.array([[1,  2], [5,  6], [9, 10]])
arr = arr[(0, 2), :]
print(arr)

导致:

[[ 1  2]
 [ 9 10]]

但是,这不会释放从排除行占用的内存。它可能会提高性能,但在记忆方面,您可能会遇到相同或更糟的问题。另请注意,据我所知,没有办法通过排除进行索引(例如arr[~1]非常有用),这必然会使您在构建索引数组时花费资源。

对于大多数情况,我认为其他用户提出的建议,即:

arr = numpy.delete(arr, 1, 0)

,是最好的。在某些情况下,可能值得探索另一种选择。

编辑: *这实际上是错误的(感谢@ user2357112)。花式索引不会创建一个视图,而是返回一个副本,如documentation中所示(在得出结论之前我应该​​检查一下,对不起):

Advanced indexing always returns a copy of the data (contrast with basic slicing that returns a view).

因此我不确定花哨的索引建议是否值得作为实际建议,除非它对np.delete方法有任何性能提升(我会尝试验证何时机会)出现,参见EDIT2 )。

EDIT2:我进行了一项非常简单的测试,看看是否通过反对删除功能使用花式索引来获得任何性能提升。使用过的timeit(实际上我第一次使用,但似乎每个代码段的执行次数是1 000 000,因此时间数量很高):

import numpy as np
import timeit

def test1():
    arr = np.array([[1, 2], [5, 6], [9, 10]])
    arr = arr[(0, 2), :]

def test2():
    arr = np.array([[1, 2], [5, 6], [9, 10]])
    arr = np.delete(arr, 1, 0)

print("Equality test: ", test1() == test2())

print(timeit.timeit("test1()", setup="from __main__ import test1"))
print(timeit.timeit("test2()", setup="from __main__ import test2"))

结果如下:

Equality test:  True
5.43569152576767
9.476918448174644

这代表了非常可观的速度增益。然而,请注意,为花式索引构建序列需要时间。如果它值得与否肯定取决于正在解决的问题。

答案 3 :(得分:1)

You could implement your own version of delete which copies data elements after the elements to be deleted forward, and then returns a view excluding the (now obsolete) last element:

import numpy as np


# in-place delete
def np_delete(arr, obj, axis=None):
    # this is a only simplified example
    assert (isinstance(obj, int))
    assert (axis is None)

    for i in range(obj + 1, arr.size):
        arr[i - 1] = arr[i]
    return arr[:-1]


Test = 10 * np.arange(10)
print(Test)

deleteIndex = 5
print(np.delete(Test, deleteIndex))
print(np_delete(Test, deleteIndex))

答案 4 :(得分:0)

您的代码没有错。你只需override变量

    arr = np.array([[1,2], [5,6], [9,10]])
    arr = np.delete(arr, 1, 0)