从numpy数组中删除一些元素

时间:2016-02-27 16:12:50

标签: 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 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

为什么只有在删除最后一个元素时才会出现此错误?什么是正确的方法来完成这些任务?

6 个答案:

答案 0 :(得分:10)

请记住,np.delete(arr,ind)会删除索引@Id @Column(name = "prefil_id") @GeneratedValue(strategy = GenerationType.AUTO) private Integer id; 处的元素,而不会删除具有该值的元素。

这意味着当您删除内容时,数组会变短。所以你从

开始
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) 

或者:

inds_to_delete = sorted([3,1,5], reverse=True) # [5,3,1]
# then delete in order of largest to smallest ind

答案 1 :(得分:3)

问题是您已从values删除了项目,因此当您尝试删除索引5中的项目时,该索引上不再有值,它现在位于索引{ {1}}。

如果您对要删除的索引列表进行排序,并将它们从大到小迭代,应解决此问题。

4

答案 2 :(得分:3)

一种可能更快的方法(因为你不需要删除所有单个值但是一次全部删除)是使用布尔掩码:

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.

建议在np.delete

上的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 :(得分:2)

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

如果你想在第一种情况下删除第四个(index = 3)项,那么剩下的第五个,最后是剩下的第二个,由于操作的顺序,你删除第二个,第四个和初始数组的第六个。因此,第二种情况失败了。

你可以用这种方式计算变化(在第五个例子中变为第六个):

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])

N.B。如果错误的指标在列表中,则np.delete不会抱怨什么都不做:np.delete(values,[8])values

答案 4 :(得分:0)

删除布尔索引。你可以使用函数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)

答案 5 :(得分:0)

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

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

>>> 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])