Currently I have the following cython function, modifies entries of a numpy array filled with zeros to sum non-zero values. Before I return the array, I would like to trim it and remove all the non-zero entries. At the moment, I use the numpy function myarray = myarray[~np.all(myarray == 0, axis=1)] to do so. I was wondering if there is (in general) a faster way to do this using a Cython/C function instead of relying on python/numpy. This is one of the last bits of pythonic interactions in my script (checked by using to %%cython -a). But I don't really know how to proceed with this problem. In general, i don't know a priori the number of nonzero elements in the final array.
cdef func():
np.ndarray[np.float64_t, ndim=2] myarray = np.zeros((lenpropen, 6))
"""
computations
"""
myarray = myarray[~np.all(myarray == 0, axis=1)]
return myarray
Thanks to @Jérôme Richard for his comments. based on that (if my understanding is correct) I tried to implement the erase-remove idiom. Sample code given below.
myarray = np.zeros((5000,6))
myarray[2] = [1,1,1,1,1,1]
@cython.boundscheck(False) # Deactivate bounds checking
@cython.wraparound(False) # Deactivate negative indexing.
@cython.cdivision(True) # Deactivate division by 0 checking.
cdef erase_remove( np.ndarray[np.float64_t, ndim=2] myarray):
cdef int idx
cdef int cursor = 0
cdef int length_arr = 5000
for idx in range(5000):
if myarray[idx,0]!=0 and myarray[idx,1]!=0 and myarray[idx,2]!=0 and myarray[idx,3]!=0 and myarray[idx,4]!=0 and myarray[idx,5]!=0:
myarray[cursor,0] = myarray[idx,0]
myarray[cursor,1] = myarray[idx,1]
myarray[cursor,2] = myarray[idx,2]
myarray[cursor,3] = myarray[idx,3]
myarray[cursor,4] = myarray[idx,4]
myarray[cursor,5] = myarray[idx,5]
cursor = cursor +1
else:
continue
return myarray[0:cursor]
start = timer()
myarray= erase_remove(myarray)
end = timer()
print("final", myarray)
print("time", end-start)
This yields the output
final [[1. 1. 1. 1. 1. 1.]]
time 1.1235475540161133e-05
Compared to
myarray = np.zeros((5000,6))
print(myarray)
myarray[2] = [1,1,1,1,1,1]
print(myarray)
start = timer()
myarray = myarray[~np.all(myarray == 0, axis=1)]
end = timer()
print(myarray)
print("time", end-start)
which yields output
[[1. 1. 1. 1. 1. 1.]]
time 0.0006445050239562988