从数组中删除每个第n个元素

20

如何在数组中删除每个第n个元素?

import numpy as np

x = np.array([0,10,27,35,44,32,56,35,87,22,47,17])
n = 3  # remove every 3rd element

有没有类似于 x[0::n] 相反的东西?我已经尝试了这个,但显然它不起作用:

for i in np.arange(0,len(x),n):
    x = np.delete(x,i)
3个回答

21

你离正确答案很近了…尝试将整个arange作为子序列传递给删除函数,而不是尝试逐个删除每个元素,例如:

del my_array[np.arange(3, 6)]

import numpy as np

x = np.array([0,10,27,35,44,32,56,35,87,22,47,17])
x = np.delete(x, np.arange(0, x.size, 3))
# [10 27 44 32 35 87 47 17]

5
实际上,最好使用 np.delete(x, slice(None, None, 3)) 来完成此操作。 - Jaime
1
@Jaime 观察得非常好 - 我没想到要检查 np.delete 是否使用原生的 slice 对象! 即使在一个百万项的数组中,似乎也没有任何速度优势(实际上略微慢一点)- 但它很好知道 - 谢谢。 - Jon Clements
1
很奇怪...在我的系统上,从一个100万项长的数组中删除每三个项目,使用切片的速度大约快1.7倍:a = np.random.rand(1e6); %timeit np.delete(a, np.arange(0, 1e6, 3)) --> 100 loops, best of 3: 14.5 ms per loop; %timeit np.delete(a, slice(None, None, 3)) --> 100 loops, best of 3: 8.41 ms per loop. - Jaime
1
@Jaime 使用那段精确的代码:372/365... 但是偶尔会交换 - 嗯... - Jon Clements
1
@Jaime 出于科学的兴趣,我也进行了测试,但使用了更大的数组。结果表明每次循环使用切片稍微更快,.251 毫秒对 .267 毫秒。 - kingledion
你也可以使用 np.delete(x, np.s_[::3]),参见此处的最后一个示例以及 np.s_ 的文档此处 - Levi Baguley

5
如果你的数组长度是n的倍数,我可以给你另一种使用重塑方法的方式:

只需将数组重塑成(n, -1)的形状即可:

import numpy as np

x = np.array([0,10,27,35,44,32,56,35,87,22,47,17])
x = x.reshape(-1,3)[:,1:].flatten()
# [10 27 44 32 35 87 47 17]

在我的计算机上,它的运行速度比使用 np.delete 的解决方案快了近两倍(说实话是1.8倍到1.9倍之间)。

您还可以轻松地执行精细操作,例如每n个值进行m次删除等。


0
这里有一个针对二维数组的超快版本:从一个二维数组中删除每第m行和第n列(假设数组的形状是(n, m)的倍数)。
array2d = np.arange(60).reshape(6, 10)
m, n = (3, 5)
remove = lambda x, q: x.reshape(x.shape[0], -1, q)[..., 1:].reshape(x.shape[0], -1).T

remove(remove(array2d, n), m)

返回:
array([[11, 12, 13, 14, 16, 17, 18, 19],
       [21, 22, 23, 24, 26, 27, 28, 29],
       [41, 42, 43, 44, 46, 47, 48, 49],
       [51, 52, 53, 54, 56, 57, 58, 59]])

为了泛化到任何形状,请根据您的情况使用填充或缩小输入数组。


速度比较:

from time import time

'remove'
start = time()
for _ in range(100000):
    res = remove(remove(array2d, n), m)
time() - start

'delete'
start = time()
for _ in range(100000):
    tmp = np.delete(array2d, np.arange(0, array2d.shape[0], m), axis=0)
    res = np.delete(tmp, np.arange(0, array2d.shape[1], n), axis=1)
time() - start

"""
'remove'
0.3835930824279785
'delete'
3.173515558242798
"""

因此,与numpy.delete相比,上述方法速度显著更快。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接