Ваша функция возвращает массив при наличии скаляра:
In [233]: def dummy(x):
...: y = np.array([np.sin(x), np.cos(x)])
...: return y
...:
...:
In [234]: dummy(1)
Out[234]: array([0.84147098, 0.54030231])
In [235]: f = np.vectorize(dummy)
In [236]: f([0,1,2])
...
ValueError: setting an array element with a sequence.
vectorize
создает пустой массив результатов и пытается поместить в него результат каждого вычисления.Но ячейка целевого массива не может принять массив.
Если мы указываем параметр otypes
, он работает:
In [237]: f = np.vectorize(dummy, otypes=[object])
In [238]: f([0,1,2])
Out[238]:
array([array([0., 1.]), array([0.84147098, 0.54030231]),
array([ 0.90929743, -0.41614684])], dtype=object)
То есть каждый массив dummy
помещаетсяв элементе shape (3,) результирующего массива.
Поскольку массивы компонентов имеют одинаковую форму, мы можем stack
их:
In [239]: np.stack(_)
Out[239]:
array([[ 0. , 1. ],
[ 0.84147098, 0.54030231],
[ 0.90929743, -0.41614684]])
Но, как отмечалось, vectorize
не обещает ускорения.Я подозреваю, что мы могли бы также использовать более новый параметр signature
, но это еще медленнее.
vectorize
имеет некоторый смысл, если ваша функция принимает несколько скалярных аргументов, и вы хотели бы использовать преимущества широковещательной трансляции, когдакормление наборов ценностей.Но как замена простой итерации над 1d-массивом, это не улучшение.