Removing all zeros from an array

  • A+

I have an array of shape [120000, 3] in which only the first 1500 elements are useful and the others are 0.

Here an example

[15.0, 14.0, 13.0] [11.0, 7.0, 8.0] [4.0, 1.0, 3.0] [0.0, 0.0, 0.0] [0.0, 0.0, 0.0] [0.0, 0.0, 0.0] [0.0, 0.0, 0.0] 

I have to find a way to remove all the elements that are [0.0, 0.0, 0.0]. I tried to write this but it doesn't work

for point in points:         if point[0] == 0.0 and point[1] == 0.0 and point[2] == 0.0:             np.delete(points, point) 


All the solutions in the comment work, but I gave the green tick to the one I have used. Thanks to all.


There are a few related approaches, split into two camps. You can either use a vectorised approach via calculation of a single Boolean array and np.ndarray.all. Or you can calculate the index of the first row which contains only 0 elements, either via a for loop or next with a generator expression.

For performance, I recommend you use numba with a manual for loop. Here's one example, but see benchmarking below for a more efficient variant:

from numba import jit  @jit(nopython=True) def trim_enum_nb(A):     for idx in range(A.shape[0]):         if (A[idx]==0).all():             break     return A[:idx] 

Performance benchmarking

# python 3.6.5, numpy 1.14.3  %timeit trim_enum_loop(A)  # 8.57 ms %timeit trim_enum_nb(A)    # 200 µs %timeit trim_enum_nb2(A)   # 2.3 µs %timeit trim_enum_gen(A)   # 8.3 ms %timeit trim_vect(A)       # 3.08 ms 

Test code


import numpy as np from numba import jit  np.random.seed(0)  n = 120000 k = 1500  A = np.random.randint(1, 10, (n, 3)) A[k:, :] = 0 


def trim_enum_loop(A):     for idx, row in enumerate(A):         if (row==0).all():             break     return A[:idx]  @jit(nopython=True) def trim_enum_nb(A):     for idx in range(A.shape[0]):         if (A[idx]==0).all():             break     return A[:idx]  @jit(nopython=True) def trim_enum_nb2(A):     for idx in range(A.shape[0]):         res = False         for col in range(A.shape[1]):             res |= A[idx, col]             if res:                 break             return A[:idx]  def trim_enum_gen(A):     idx = next(idx for idx, row in enumerate(A) if (row==0).all())     return A[:idx]  def trim_vect(A):     idx = np.where((A == 0).all(1))[0][0]     return A[:idx] 


# check all results are the same assert (trim_vect(A) == trim_enum_loop(A)).all() assert (trim_vect(A) == trim_enum_nb(A)).all() assert (trim_vect(A) == trim_enum_nb2(A)).all() assert (trim_vect(A) == trim_enum_gen(A)).all() 


:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: