vectorize
предназначен для использования с scalar
функциями, которые принимают скалярные входные данные и возвращают скалярные выходные данные.
In [729]: foo(z,10)
Out[729]:
array([[1, 2, 3],
[1, 2, 3],
[1, 2, 3],
[1, 2, 3],
[1, 2, 3],
[1, 2, 3],
[1, 2, 3],
[1, 2, 3],
[1, 2, 3],
[1, 2, 3]])
In [730]: bar(z)
Out[730]:
array([[1, 2, 3],
[1, 2, 3],
[1, 2, 3],
[1, 2, 3],
[1, 2, 3],
[1, 2, 3],
[1, 2, 3],
[1, 2, 3],
[1, 2, 3],
[1, 2, 3]])
Ваш bar
возвращает 2d массив, если ему дано 1d вход. Или 1d массив, если дан скалярный вход
In [734]: bar(4)
Out[734]: array([4, 4, 4, 4, 4, 4, 4, 4, 4, 4])
Мы можем vectorize
ожидать, что object
возврат
In [735]: barv = np.vectorize(bar, otypes=[object])
In [736]: barv(4)
Out[736]: array([4, 4, 4, 4, 4, 4, 4, 4, 4, 4], dtype=object)
In [737]: barv(z)
Out[737]:
array([array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1]),
array([2, 2, 2, 2, 2, 2, 2, 2, 2, 2]),
array([3, 3, 3, 3, 3, 3, 3, 3, 3, 3])], dtype=object)
, который можно превратить в 2d массив :
In [738]: np.stack(_)
Out[738]:
array([[1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[2, 2, 2, 2, 2, 2, 2, 2, 2, 2],
[3, 3, 3, 3, 3, 3, 3, 3, 3, 3]])
vectorize
также имеет параметр подписи, который может помочь в этом случае. Но по моему опыту это даже медленнее.
Но нам не нужно vectorize
здесь - простое понимание списка такое же хорошее, возможно, лучше:
In [739]: np.stack([bar(i) for i in z])
Out[739]:
array([[1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[2, 2, 2, 2, 2, 2, 2, 2, 2, 2],
[3, 3, 3, 3, 3, 3, 3, 3, 3, 3]])
vectorize
делает «вещание» с несколькими входными массивами проще, но это не улучшает скорость. Посмотрите, сможете ли вы выяснить, что vectorize
делает здесь с foo
:
In [743]: f = np.vectorize(foo, otypes=[object])
In [744]: f(np.array([1,2,3]), np.array([2,3,4]))
Out[744]: array([array([1, 1]), array([2, 2, 2]), array([3, 3, 3, 3])], dtype=object)
In [745]: f(np.array([1,2,3]), np.array([[2],[3]]))
Out[745]:
array([[array([1, 1]), array([2, 2]), array([3, 3])],
[array([1, 1, 1]), array([2, 2, 2]), array([3, 3, 3])]],
dtype=object)
edit
Правильно numpy
векторизация:
In [762]: np.repeat(z[:,None],10,1)
Out[762]:
array([[1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[2, 2, 2, 2, 2, 2, 2, 2, 2, 2],
[3, 3, 3, 3, 3, 3, 3, 3, 3, 3]])
Некоторые Сравнение времени:
In [766]: timeit np.stack(barv(z))
60 µs ± 1.35 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
In [767]: timeit np.stack([bar(i) for i in z])
39.6 µs ± 132 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
In [768]: timeit np.repeat(z[:,None],10,1)
4.12 µs ± 14.6 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
Ваш foo
уже работает с входом массива. Не было необходимости в np.vectorize
обертке.
In [783]: foo(z,10).T
Out[783]:
array([[1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[2, 2, 2, 2, 2, 2, 2, 2, 2, 2],
[3, 3, 3, 3, 3, 3, 3, 3, 3, 3]])
In [784]: timeit foo(z,10).T
10.8 µs ± 364 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)