numpy.vectorize
берет функцию f:a-> b и превращает его в g:a []-> b [].
Это хорошо работает когда a
и b
скаляры, но я не могу думать о причине, почему она не работала бы с b как ndarray
или список, т.е. f:a-> b [] и g:a []-> b [] []
Например:
import numpy as np
def f(x):
return x * np.array([1,1,1,1,1], dtype=np.float32)
g = np.vectorize(f, otypes=[np.ndarray])
a = np.arange(4)
print(g(a))
Это уступает:
array([[ 0. 0. 0. 0. 0.],
[ 1. 1. 1. 1. 1.],
[ 2. 2. 2. 2. 2.],
[ 3. 3. 3. 3. 3.]], dtype=object)
Хорошо, так, чтобы дает правильные значения, но несправедливость dtype. И еще хуже:
g(a).shape
урожаи:
(4,)
Таким образом, этот массив в значительной степени бесполезен. Я знаю, что могу преобразовать его делающий:
np.array(map(list, a), dtype=np.float32)
чтобы дать мне, что я хочу:
array([[ 0., 0., 0., 0., 0.],
[ 1., 1., 1., 1., 1.],
[ 2., 2., 2., 2., 2.],
[ 3., 3., 3., 3., 3.]], dtype=float32)
но это ни эффективно, ни pythonic. Может какой-либо из Вас, парни находят более чистый способ сделать это?
Заранее спасибо!
np.vectorize
- это просто удобная функция. На самом деле она не заставляет код работать быстрее. Если вам неудобно использовать np.vectorize
, просто напишите свою собственную функцию, которая работает так, как вы хотите.
Цель np.vectorize
- преобразовать функции, которые не являются numpy-aware (например, принимают floats на вход и возвращают floats на выход), в функции, которые могут работать с массивами numpy (и возвращать их).
Ваша функция f
уже numpy-aware - она использует numpy-массив в своем определении и возвращает numpy-массив. Поэтому np.vectorize
не подходит для вашего случая использования.
Поэтому решением является создание собственной функции f
, которая работает так, как вы хотите.