20

How do I remove every nth element in an array?

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

...something like the opposite of x[0::n]? I've tried this, but of course it doesn't work:

for i in np.arange(0,len(x),n):
    x = np.delete(x,i)
codeforester
  • 39,467
  • 16
  • 112
  • 140
Medulla Oblongata
  • 3,771
  • 8
  • 36
  • 75

3 Answers3

21

You're close... Pass the entire arange as subslice to delete instead of attempting to delete each element in turn, eg:

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]
Jon Clements
  • 138,671
  • 33
  • 247
  • 280
  • 5
    That is actually much better done as `np.delete(x, slice(None, None, 3))`. – Jaime Feb 21 '14 at 00:42
  • 1
    @Jaime very nice observation - didn't think to check if `np.delete` took native `slice` objects! There doesn't seem to be any speed advantage though even with a million item array (in fact it's ever so *slightly slower*) - but it's good to know - thanks. – Jon Clements Feb 21 '14 at 00:54
  • 1
    That's weird... On my system, removing every third item of a 1 million item long array is about 1.7x faster with the slice: `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 Feb 21 '14 at 01:38
  • 1
    @Jaime Using that exact code: 372/365... But swaps around occasionally - umm.... – Jon Clements Feb 21 '14 at 01:43
  • 1
    @Jaime In the interests of science, I tested this as well, but on a much larger array. I got that slice was moderately faster per loop, .251 to .267 ms. – kingledion Mar 05 '17 at 22:27
  • you can also do `np.delete(x, np.s_[::3])` see the last example [here](https://numpy.org/doc/stable/reference/generated/numpy.delete.html) and the doc for `np.s_` [here](https://numpy.org/doc/stable/reference/generated/numpy.s_.html) – Levi Baguley Aug 18 '21 at 15:35
5

I just add another way with reshaping if the length of your array is a multiple of n:

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]

On my computer it runs almost twice faster than the solution with np.delete (between 1.8x and 1.9x to be honnest).

You can also easily perfom fancy operations, like m deletions each n values etc.

Remy F
  • 1,479
  • 15
  • 20
0

Here's a super fast version for 2D arrays: Remove every m-th row and n-th column from a 2D array (assuming the shape of the array is a multiple of (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)

returns:

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

To generalize for any shape use padding or reduce the input array depending on your situation.


Speed comparison:

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
"""

So, compared to numpy.delete the above method is significantly faster.

isCzech
  • 313
  • 1
  • 1
  • 7