一个有趣的问题:
我想从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
为什么只有在删除最后一个元素时才会出现此错误?什么是正确的方法来完成这些任务?
答案 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
对于你的问题:删除一个元素,使数组变得更短,索引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])