Альтернатива с использованием Cython
Если вы можете использовать Cython, вы можете использовать что-то вроде следующего, которое можно запустить из ноутбука Jupyter с помощью следующих
%load_ext Cython
Тогда в отдельной ячейке запустите.
%%cython -a
from cython cimport boundscheck, wraparound
cimport numpy as np
import numpy as np
@boundscheck(False)
@wraparound(False)
def cython_sticky_cumsum(int[::1] a, int[::1] b):
cdef size_t i, N = a.size
cdef np.ndarray[np.int32_t, ndim=1] result = np.empty(N, dtype=np.int32)
for i in range(N):
if a[i] == 1:
result[i] = 1
elif b[i] == :
result[i] = 0
else:
result[i] = result[i-1]
return result
Если вас интересует производительность / использование больших массивов, может быть предпочтительнее что-то подобное вышеописанному. Я думаю, это зависит от того, что вы находите более читабельным.
a = np.array([1, 0, 0, 0, 1, 0])
b = np.array([0, 0, 1, 0, 0, 0])
cython_sticky_cumsum(a, b)
# array([1, 1, 0, 0, 1, 1])
Необработанный тест
Для гораздо больших массивов, таких как
a = np.tile(np.array([1, 0, 0, 0, 1, 0]), 1000000)
b = np.tile(np.array([0, 0, 1, 0, 0, 0]), 1000000)
и выполнение тестов,
%timeit cython_sticky_cumsum(a,b)
%timeit sticky_cumsum(a, b)
выходы
28.4 ms ± 1.86 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
2.5 s ± 97.2 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)