Python 从numpy数组中删除一些元素

Python 从numpy数组中删除一些元素,python,numpy,Python,Numpy,一个有趣的问题: 我想从numpy数组中删除一些元素,但正如下面的简化示例代码所示,如果不删除最后一个元素,它可以工作,但是如果我们希望删除最后一个元素,它将失败。 以下代码可以正常工作: import numpy as np values = np.array([0,1,2,3,4,5]) print values for i in [3,4,1]: values = np.delete(values,i) print values 输出为: [0 1 2 3 4 5] [0 2

一个有趣的问题:

我想从numpy数组中删除一些元素,但正如下面的简化示例代码所示,如果不删除最后一个元素,它可以工作,但是如果我们希望删除最后一个元素,它将失败。 以下代码可以正常工作:

import numpy as np

values = np.array([0,1,2,3,4,5])
print values
for i in [3,4,1]:
    values = np.delete(values,i)
print values
输出为:

[0 1 2 3 4 5]
[0 2 4]
如果我们只将4改为5,那么它将失败:

import numpy as np

values = np.array([0,1,2,3,4,5])
print values
for i in [3,5,1]:
    values = np.delete(values,i)
print values
错误消息:

IndexError: index 5 is out of bounds for axis 0 with size 5

为什么只有删除最后一个元素时才会发生此错误?执行此类任务的正确方法是什么?

请记住,np.delete(arr,ind)删除索引
ind
处的元素,而不是具有该值的元素

这意味着当您删除内容时,数组将变短。那么你从

values = [0,1,2,3,4,5]
np.delete(values, 3) 
[0,1,2,4,5]  #deleted element 3 so now only 5 elements in the list
#tries to delete the element at the fifth index but the array indices only go from 0-4
np.delete(values, 5) 
解决此问题的方法之一是按降序对要删除的索引进行排序(如果确实要删除数组)

或:


问题是您已经从
值中删除了项目
,因此当您试图删除索引
5
中的项目时,该索引中不再有值,它现在位于索引
4

如果您对要删除的索引列表进行排序,并从大到小对其进行迭代,则应该可以解决此问题

import numpy as np

values = np.array([0,1,2,3,4,5])
print values
for i in [5,3,1]:  # iterate in order
    values = np.delete(values,i)
print values
一种可能更快的方法(因为您不需要删除每个值,而是一次删除所有值)是使用布尔掩码:

values = np.array([0,1,2,3,4,5])
tobedeleted = np.array([False, True, False, True, False, True])
# So index 3, 5 and 1 are True so they will be deleted.
values_deleted = values[~tobedeleted]
#that just gives you what you want.
建议在上的numpy参考上使用

对于您的问题:删除一个元素,使数组变短,索引5不再在数组中,因为以前的索引5现在有索引4。如果要使用np.Delete,请按降序删除

如果您确实想使用
np.delete
删除,请使用速记:

np.delete(values, [3,5,1])
如果要删除值所在的位置(而不是索引),则必须稍微修改该过程。如果要删除数组中的所有值
5
,可以使用:

values[values != 5]
或具有多个要删除的值:

to_delete = (values == 5) | (values == 3)  | (values == 1)
values[~to_delete]

所有这些都会给您提供所需的结果,但不确定数据的真实外观,因此我无法确定哪一个是最合适的。

如果要删除索引3,4,1的元素,只需执行
np.delete(值,[3,4,1])

如果要在第一种情况下删除第四个(index=3)项,然后删除其余的第五个项,最后删除其余的第二个项,根据操作顺序,可以删除初始数组的第二、第四和第六个项。因此,第二个案例失败是合乎逻辑的

您可以通过以下方式计算位移(在示例fifth变为sixth中):

def multidelete(values,todelete):
   todelete=np.array(todelete)
   shift=np.triu((todelete>=todelete[:,None]),1).sum(0)
   return np.delete(values,todelete+shift)
一些测试:

In [91]: multidelete([0, 1, 2, 3, 4, 5],[3,4,1])
Out[91]: array([0, 2, 4])

In [92]: multidelete([0, 1, 2, 3, 4, 5],[1,1,1])
Out[92]: array([0, 4, 5])

注意,
np.delete
不会抱怨在列表中出现错误标记时什么也不做:
np.delete(values,[8])
is
values

不推荐使用布尔索引。您可以使用函数np.where()来代替,如下所示:

values = np.array([0,1,2,3,4,5])
print(values)
for i in [3,5,1]:
    values = np.delete(values,np.where(values==i))
    # values = np.delete(values,values==i) # still works with warning
print(values)

我知道这个问题很老,但为了进一步参考(因为我发现了一个类似的源问题):

解决方案是使用numpy函数过滤数组,而不是生成for循环。这样,

>>> import numpy as np
>>> # np.isin(element, test_elements, assume_unique=False, invert=False)

>>> arr = np.array([1, 4, 7, 10, 5, 10])
>>> ~np.isin(arr, [4, 10])
array([ True, False,  True, False,  True, False])
>>> arr = arr[ ~np.isin(arr, [4, 10]) ]
>>> arr
array([1, 7, 5])
因此,对于这种特殊情况,我们可以写:

values = np.array([0,1,2,3,4,5])
torem = [3,4,1]
values = values[ ~np.isin(values, torem) ]

输出:
array([0,2,5])

是否要删除索引
[3,4,1]
中的元素或值
[3,4,1]
?这是令人困惑的,因为数组中的值与索引相同
>>> import numpy as np
>>> # np.isin(element, test_elements, assume_unique=False, invert=False)

>>> arr = np.array([1, 4, 7, 10, 5, 10])
>>> ~np.isin(arr, [4, 10])
array([ True, False,  True, False,  True, False])
>>> arr = arr[ ~np.isin(arr, [4, 10]) ]
>>> arr
array([1, 7, 5])
values = np.array([0,1,2,3,4,5])
torem = [3,4,1]
values = values[ ~np.isin(values, torem) ]