Стоит попробовать сделать это на месте, только если вы находитесь в условиях ограниченного пространства. Если это так, то можно немного ускорить ваш код, выполняя итерацию по сглаженному представлению массива. Поскольку reshape
возвращает новое представление , когда это возможно , сами данные не копируются (если оригинал не имеет необычной структуры).
Я не знаю лучшего способа добиться добросовестного применения произвольной функции Python на месте.
>>> def flat_for(a, f):
... a = a.reshape(-1)
... for i, v in enumerate(a):
... a[i] = f(v)
...
>>> a = numpy.arange(25).reshape(5, 5)
>>> flat_for(a, lambda x: x + 5)
>>> a
array([[ 5, 6, 7, 8, 9],
[10, 11, 12, 13, 14],
[15, 16, 17, 18, 19],
[20, 21, 22, 23, 24],
[25, 26, 27, 28, 29]])
Некоторые тайминги:
>>> a = numpy.arange(2500).reshape(50, 50)
>>> f = lambda x: x + 5
>>> %timeit flat_for(a, f)
1000 loops, best of 3: 1.86 ms per loop
Это примерно вдвое быстрее, чем версия с вложенным циклом:
>>> a = numpy.arange(2500).reshape(50, 50)
>>> def nested_for(a, f):
... for i in range(len(a)):
... for j in range(len(a[0])):
... a[i][j] = f(a[i][j])
...
>>> %timeit nested_for(a, f)
100 loops, best of 3: 3.79 ms per loop
Конечно, векторизация еще быстрее, поэтому, если вы можете сделать копию, используйте это:
>>> a = numpy.arange(2500).reshape(50, 50)
>>> g = numpy.vectorize(lambda x: x + 5)
>>> %timeit g(a)
1000 loops, best of 3: 584 us per loop
И если вы можете переписать dim
с помощью встроенных ufuncs, то, пожалуйста, не надо vectorize
:
>>> a = numpy.arange(2500).reshape(50, 50)
>>> %timeit a + 5
100000 loops, best of 3: 4.66 us per loop
numpy
выполняет такие операции, как +=
на месте, как и следовало ожидать - так что вы можете получить скорость ufunc с приложением на месте без каких-либо затрат. Иногда это даже быстрее! См. здесь для примера.
Кстати, мой первоначальный ответ на этот вопрос, который можно увидеть в истории его редактирования, смешен и включает в себя векторизацию индексов в a
. Мало того, что он должен был сделать что-то напуганное, чтобы обойти vectorize
механизм определения типа , он оказался таким же медленным, как версия с вложенным циклом. Так много за ум!