Редактировать: похоже, np.apply_along_axis
делает то, что вы хотите. Например:
import numpy as np
def f(x):
return x * x.sum()
X = np.arange(12).reshape(2, 2, 3)
np.apply_along_axis(f, -1, X)
# array([[[ 0, 3, 6],
# [ 36, 48, 60]],
#
# [[126, 147, 168],
# [270, 300, 330]]])
Заметки об исполнении от моего первоначального ответа ниже по-прежнему применяются. не
Оригинальный ответ:
Там нет встроенной для этого, но Python делает его простым определить таким контекстом менеджеру самостоятельно. Например:
import numpy as np
from contextlib import wraps
def row_vectorize(f):
@wraps(f)
def wrapped_f(X):
X = np.asarray(X)
rows = X.reshape(-1, X.shape[-1])
return np.reshape([f(row) for row in rows],
X.shape[:-1] + (-1,))
return wrapped_f
@row_vectorize
def func(row):
return row * row.sum()
Теперь вы можете использовать это на массивы любой ненулевой размерности:
>>> X_1D = np.arange(3)
>>> func(X_1D)
array([0, 3, 6])
>>> X_2D = np.arange(6).reshape(2, 3)
>>> func(X_2D)
array([[ 0, 3, 6],
[36, 48, 60]])
>>> X_3D = np.arange(12).reshape((2, 2, 3))
>>> func(X_3D)
array([[[ 0, 3, 6],
[ 36, 48, 60]],
[[126, 147, 168],
[270, 300, 330]]])
С точки зрения производительности, np.vectorize
делает что-то очень похожее.
Если вам нужна более быстрая петля для настраиваемой функции, применяемой к массиву, вы можете часто создавать свой метод в терминах операций с элементами numpy и сводных операций; например, эта функция выполняет то же самое, что и функция рядной векторизовано выше, но будет намного быстрее на больших входах:
def func2(X):
return X * X.sum(-1, keepdims=True)
Если у вас есть более сложные операции, вы хотите применить по строкам массива и производительность петель является узким местом, лучшие варианты, вероятно, должны использовать numba или cython.
Я просто прочитал: «Функция векторизации предоставляется в основном для удобства, а не для производительности. Реализация по существу является циклом for». Таким образом, функция в любом случае не так полезна. – Michael
Нет никакого «функционально-агностического» метода векторизации, который даст вам значительно лучшую производительность (как вы видели, «np.vectorize» - это просто синтаксический сахар). Вы можете либо переписать 'fct', чтобы принимать массивы в качестве входных аргументов, либо переключиться на скомпилированную реализацию (например, Cython, numba). –
Чтобы добавить к предложению @ ali_m, вы можете попробовать обобщенный ufunc numba http://numba.pydata.org/numba-doc/dev/user/vectorize.html#the-guvectorize-decorator. Помимо любого увеличения скорости, он делает интеллектуальное вещание, которое вы хотите. – DavidW