如何从numpy数组中一次排除少数范围?

时间:2015-09-22 18:13:46

标签: python arrays numpy

说,有一个跟随numpy数组:

X = numpy.array([1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5])

现在,如何从数组X中排除X[0:2]X[6:8]X[12:14]范围,以便一个人进入结果X= [2, 2, 2, 4, 4, 4]

5 个答案:

答案 0 :(得分:1)

您可以使用以下内容:

numbers = [1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5]
exclude = set(range(0,2) + range(6,8) + range(12,14))
[n for n in numbers if n not in exclude]

或:

[i for i in nums if i not in xrange(0,2) and i not in xrange(6,8) and i not in xrange(12,14)]

结果:

[2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5]

答案 1 :(得分:1)

在对@unutbu的答案的评论中,我建议np.delete。这里有几个时间

更大的测试阵列:

In [445]: A=np.arange(1000)

@ unutbu的回答:

In [446]: timeit A[~np.in1d(np.arange(len(A)), (np.r_[10:50:3,100:200,300:350]))].shape
1000 loops, best of 3: 454 µs per loop

相同的索引列表,但使用np.delete - 大约3倍加速

In [447]: timeit np.delete(A,np.r_[10:50:3,100:200,300:350]).shape
10000 loops, best of 3: 166 µs per loop

但是直接进行布尔屏蔽会更快。之前我推断np.delete基本上做了这个,但它必须有一些额外的开销(包括处理多个维度的能力):

In [448]: %%timeit
ind=np.ones_like(A,bool)
ind[np.r_[10:50:3,100:200,300:350]]=False
A[ind].shape
   .....: 
10000 loops, best of 3: 71.5 µs per loop
当输入是切片时,

np.delete具有不同的策略,这可能比布尔索引更快。但它一次只处理一个切片,因此@Kasramvd显示的嵌套删除。我打算补充一下时间。

连接多个切片是另一种选择。

np.r_也涉及一个循环,但它只在切片上。基本上它迭代切片,将每个切片扩展为一个范围,并将它们连接起来。在我最快的情况下,它负责运行时间的2/3:

In [451]: timeit np.r_[10:50:3,100:200,300:350]
10000 loops, best of 3: 41 µs per loop
In [453]: %%timeit x=np.r_[10:50:3,100:200,300:350]
ind=np.ones_like(A,bool)
ind[x]=False
A[ind].shape
   .....: 
10000 loops, best of 3: 24.2 µs per loop

嵌套删除具有相当不错的性能:

In [457]: timeit np.delete( np.delete( np.delete(A,slice(300,350)),
   slice(100,200)),slice(10,50,3)).shape
10000 loops, best of 3: 108 µs per loop

np.delete,当给定要删除的切片时,将切片复制到结果数组(删除块之前和之后的块)。我可以通过连接几个切片来估算它。我在这里作为第一个块使用delete来作弊,而不是花时间写一个纯副本。它仍然比最好的布尔掩码表达式快。

In [460]: timeit np.concatenate([np.delete(A[:100],slice(10,50,3)),
   A[200:300],A[350:]]).shape
10000 loops, best of 3: 65.7 µs per loop

我可以通过这个切片移除delete,尽管10:50范围的顺序搞砸了。我怀疑这在理论上是最快的:

In [480]: timeit np.concatenate([A[:10], A[11:50:3], A[12:50:3],
    A[50:100], A[200:300], A[350:]]).shape
100000 loops, best of 3: 16.1 µs per loop

一个重要的警告 - 这些替代方案正在使用非重叠切片进行测试。有些可能与重叠有关,有些可能没有。

答案 2 :(得分:0)

根据你想要保留的间隔来组合X ..

X = np.array(list(X[3:6]) + list(X[9:12]))

答案 3 :(得分:0)

您可以拨打np.delete 3次,因为@nneonneo在评论中说它反转了哪些不需要计算范围偏移。 :

>>> np.delete(np.delete(np.delete(X,np.s_[12:14]),np.s_[6:8]),np.s_[0:2])
array([1, 2, 2, 2, 3, 4, 4, 4, 5])

答案 4 :(得分:0)

不确定这样做是否有帮助,但是如果每个范围的输出都是唯一的,则可以按范围计数编制索引。

X = numpy.array([1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5])

A = np.unique(X)

Out[79]: array([1, 2, 3, 4, 5])

在这里我们要保持第二和第四范围。

X = X[(X==A[1])|(X==A[3])]  

Out[82]: array([2, 2, 2, 4, 4, 4])