How to remove specific elements in a numpy array

PythonArraysNumpy

Python Problem Overview


How can I remove some specific elements from a numpy array? Say I have

import numpy as np

a = np.array([1,2,3,4,5,6,7,8,9])

I then want to remove 3,4,7 from a. All I know is the index of the values (index=[2,3,6]).

Python Solutions


Solution 1 - Python

Use numpy.delete() - returns a new array with sub-arrays along an axis deleted

numpy.delete(a, index)

For your specific question:

import numpy as np

a = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9])
index = [2, 3, 6]

new_a = np.delete(a, index)

print(new_a) #Prints `[1, 2, 5, 6, 8, 9]`

Note that numpy.delete() returns a new array since array scalars are immutable, similar to strings in Python, so each time a change is made to it, a new object is created. I.e., to quote the delete() docs:

> "A copy of arr with the elements specified by obj removed. Note that > delete does not occur in-place..."

If the code I post has output, it is the result of running the code.

Solution 2 - Python

There is a numpy built-in function to help with that.

import numpy as np
>>> a = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9])
>>> b = np.array([3,4,7])
>>> c = np.setdiff1d(a,b)
>>> c
array([1, 2, 5, 6, 8, 9])

Solution 3 - Python

A Numpy array is immutable, meaning you technically cannot delete an item from it. However, you can construct a new array without the values you don't want, like this:

b = np.delete(a, [2,3,6])

Solution 4 - Python

To delete by value :

modified_array = np.delete(original_array, np.where(original_array == value_to_delete))

Solution 5 - Python

Using np.delete is the fastest way to do it, if we know the indices of the elements that we want to remove. However, for completeness, let me add another way of "removing" array elements using a boolean mask created with the help of np.isin. This method allows us to remove the elements by specifying them directly or by their indices:

import numpy as np
a = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9])

Remove by indices:

indices_to_remove = [2, 3, 6]
a = a[~np.isin(np.arange(a.size), indices_to_remove)]

Remove by elements (don't forget to recreate the original a since it was rewritten in the previous line):

elements_to_remove = a[indices_to_remove]  # [3, 4, 7]
a = a[~np.isin(a, elements_to_remove)]

Solution 6 - Python

Not being a numpy person, I took a shot with:

>>> import numpy as np
>>> import itertools
>>> 
>>> a = np.array([1,2,3,4,5,6,7,8,9])
>>> index=[2,3,6]
>>> a = np.array(list(itertools.compress(a, [i not in index for i in range(len(a))])))
>>> a
array([1, 2, 5, 6, 8, 9])

According to my tests, this outperforms numpy.delete(). I don't know why that would be the case, maybe due to the small size of the initial array?

python -m timeit -s "import numpy as np" -s "import itertools" -s "a = np.array([1,2,3,4,5,6,7,8,9])" -s "index=[2,3,6]" "a = np.array(list(itertools.compress(a, [i not in index for i in range(len(a))])))"
100000 loops, best of 3: 12.9 usec per loop

python -m timeit -s "import numpy as np" -s "a = np.array([1,2,3,4,5,6,7,8,9])" -s "index=[2,3,6]" "np.delete(a, index)"
10000 loops, best of 3: 108 usec per loop

That's a pretty significant difference (in the opposite direction to what I was expecting), anyone have any idea why this would be the case?

Even more weirdly, passing numpy.delete() a list performs worse than looping through the list and giving it single indices.

python -m timeit -s "import numpy as np" -s "a = np.array([1,2,3,4,5,6,7,8,9])" -s "index=[2,3,6]" "for i in index:" "    np.delete(a, i)"
10000 loops, best of 3: 33.8 usec per loop

Edit: It does appear to be to do with the size of the array. With large arrays, numpy.delete() is significantly faster.

python -m timeit -s "import numpy as np" -s "import itertools" -s "a = np.array(list(range(10000)))" -s "index=[i for i in range(10000) if i % 2 == 0]" "a = np.array(list(itertools.compress(a, [i not in index for i in range(len(a))])))"
10 loops, best of 3: 200 msec per loop

python -m timeit -s "import numpy as np" -s "a = np.array(list(range(10000)))" -s "index=[i for i in range(10000) if i % 2 == 0]" "np.delete(a, index)"
1000 loops, best of 3: 1.68 msec per loop

Obviously, this is all pretty irrelevant, as you should always go for clarity and avoid reinventing the wheel, but I found it a little interesting, so I thought I'd leave it here.

Solution 7 - Python

In case you don't have the indices of the elements you want to remove, you can use the function in1d provided by numpy.

The function returns True if the element of a 1-D array is also present in a second array. To delete the elements, you just have to negate the values returned by this function.

Notice that this method keeps the order from the original array.

In [1]: import numpy as np

        a = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9])
        rm = np.array([3, 4, 7])
        # np.in1d return true if the element of `a` is in `rm`
        idx = np.in1d(a, rm)
        idx

Out[1]: array([False, False,  True,  True, False, False,  True, False, False])

In [2]: # Since we want the opposite of what `in1d` gives us, 
        # you just have to negate the returned value
        a[~idx]

Out[2]: array([1, 2, 5, 6, 8, 9])

Solution 8 - Python

If you don't know the index, you can't use logical_and

x = 10*np.random.randn(1,100)
low = 5
high = 27
x[0,np.logical_and(x[0,:]>low,x[0,:]<high)]

Solution 9 - Python

Remove specific index(i removed 16 and 21 from matrix)

import numpy as np
mat = np.arange(12,26)
a = [4,9]
del_map = np.delete(mat, a)
del_map.reshape(3,4)

Output:

array([[12, 13, 14, 15],
      [17, 18, 19, 20],
      [22, 23, 24, 25]])

Solution 10 - Python

list comprehension could be an interesting approach as well.

a = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9])
index = np.array([2, 3, 6]) #index is changed to an array.  
out = [val for i, val in enumerate(a) if all(i != index)]
>>> [1, 2, 5, 6, 8, 9]

Solution 11 - Python

You can also use sets:

a = numpy.array([10, 20, 30, 40, 50, 60, 70, 80, 90])
the_index_list = [2, 3, 6]

the_big_set = set(numpy.arange(len(a)))
the_small_set = set(the_index_list)
the_delta_row_list = list(the_big_set - the_small_set)

a = a[the_delta_row_list]

Solution 12 - Python

Filter the part that you do not need:

import numpy as np
a = np.array([1,2,3,4,5,6,7,8,9])
a = a[(a!=3)&(a!=4)&(a!=7)]

If you have a list of indices to be removed:

to_be_removed_inds = [2,3,6]
a = np.array([1,2,3,4,5,6,7,8,9])
a = a[[x for x in range(len(a)) if x not in to_be_removed]]

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionDaniel Thaagaard AndreasenView Question on Stackoverflow
Solution 1 - PythonLevonView Answer on Stackoverflow
Solution 2 - PythonZongView Answer on Stackoverflow
Solution 3 - PythonDigitalexView Answer on Stackoverflow
Solution 4 - PythonPrakhar PandeyView Answer on Stackoverflow
Solution 5 - PythonAndreas K.View Answer on Stackoverflow
Solution 6 - PythonGareth LattyView Answer on Stackoverflow
Solution 7 - PythonLuiz Otavio V. B. OliveiraView Answer on Stackoverflow
Solution 8 - PythonidnavidView Answer on Stackoverflow
Solution 9 - PythonRaja Ahsan ZebView Answer on Stackoverflow
Solution 10 - PythonMauricio ArboledaView Answer on Stackoverflow
Solution 11 - PythonOlDorView Answer on Stackoverflow
Solution 12 - PythonkeramatView Answer on Stackoverflow