Более быстрое внедрение
Это скомпилированная версия, использующая набор в качестве решения для понимания списка @Matt Messersmith. Это в основном замена более медленного метода np.isin. У меня были некоторые проблемы со случаем, когда index_to_remove
является скалярным значением, и я реализовал отдельную версию для этого случая.
Код
import numpy as np
import numba as nb
@nb.njit(parallel=True)
def in1d_vec_nb(matrix, index_to_remove):
#matrix and index_to_remove have to be numpy arrays
#if index_to_remove is a list with different dtypes this
#function will fail
out=np.empty(matrix.shape[0],dtype=nb.boolean)
index_to_remove_set=set(index_to_remove)
for i in nb.prange(matrix.shape[0]):
if matrix[i] in index_to_remove_set:
out[i]=False
else:
out[i]=True
return out
@nb.njit(parallel=True)
def in1d_scal_nb(matrix, index_to_remove):
#matrix and index_to_remove have to be numpy arrays
#if index_to_remove is a list with different dtypes this
#function will fail
out=np.empty(matrix.shape[0],dtype=nb.boolean)
for i in nb.prange(matrix.shape[0]):
if (matrix[i] == index_to_remove):
out[i]=False
else:
out[i]=True
return out
def isin_nb(matrix_in, index_to_remove):
#both matrix_in and index_to_remove have to be a np.ndarray
#even if index_to_remove is actually a single number
shape=matrix_in.shape
if index_to_remove.shape==():
res=in1d_scal_nb(matrix_in.reshape(-1),index_to_remove.take(0))
else:
res=in1d_vec_nb(matrix_in.reshape(-1),index_to_remove)
return res.reshape(shape)
Пример
data = np.array([[80,1,12],[160,2,12],[240,3,12],[80,4,11]])
test_elts= np.array((80))
data[isin_nb(data[:,0],test_elts),:]
Tmings
test_elts = np.arange(12345)
data=np.arange(1000*1000)
#The first call has compilation overhead of about 300ms
#which is not included in the timings
#remove_from_result: 52ms
#isin_nb: 1.59ms