Можно уменьшить два цикла for
до одного цикла for
, добавив при этом немного дополнительных затрат на копирование.
In [86]: a
Out[86]:
array([[1., 1., 1., 1.],
[1., 1., 1., 1.],
[1., 1., 1., 1.],
[1., 1., 1., 1.]])
In [87]: b = a.copy()
In [88]: for col in range(b.shape[1]-1):
...: b[:, col+1] = np.sum(a[:, :col+2], axis=1)
In [89]: b
Out[89]:
array([[1., 2., 3., 4.],
[1., 2., 3., 4.],
[1., 2., 3., 4.],
[1., 2., 3., 4.]])
Чтобы это работало для универсальной функции , вы можете найти эквивалентную функцию в numpy или реализовать ее с помощью numpy операций (векторизованной).В приведенном вами примере я просто использовал numpy.sum()
, который делает эту работу за нас.
С точки зрения производительности этот подход был бы намного лучше, чем работа с использованием двух циклов for
на уровне индексов, особеннодля больших массивов.В подходе, который я использовал выше, мы работаем со срезами столбцов.
Вот моменты времени, которые предполагают более чем 3X ускорение по сравнению с собственной реализацией Python.
Родной Python:
def fn(a):
b = np.array(a)
for i in range(b.shape[0]):
for j in range(b.shape[1] - 1):
b[i][j+1] += b[i][j]
return b
Немного векторизовано:
In [104]: def slightly_vectorized(b):
...: for col in range(b.shape[1]-1):
...: b[:, col+1] = np.sum(a[:, :col+2], axis=1)
...: return b
In [100]: a = np.ones(625).reshape(25, 25)
In [101]: %timeit fn(a)
303 µs ± 2.05 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
In [102]: b = a.copy()
In [103]: %timeit slightly_vectorized(b)
99.8 µs ± 501 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)