我正在尝试对输出列表的函数进行矢量化。我希望从numpy列表中提取所有值并让它返回一个矩阵,这样每行都是输入向量中元素的输出。
import numpy as np
def func(x, n):
o = []
for i in range(n):
o.append(x+i)
return o
vec_func = np.vectorize(func)
matrix = vec_func(np.asarray([0, 1, 2]), 10)
然而我收到了错误
ValueError:使用序列设置数组元素。
我该如何解决这个问题?
答案 0 :(得分:3)
frompyfunc
可能会更好:
In [525]: def fun(x):
...: return x+.1, x+.2, x+.3
...:
我指定1个输入,3个输出值。它返回dtype对象:
In [526]: np.frompyfunc(fun,1,3)(np.arange(5))
Out[526]:
(array([0.1, 1.1, 2.1, 3.1, 4.1], dtype=object),
array([0.2, 1.2, 2.2, 3.2, 4.2], dtype=object),
array([0.3, 1.3, 2.3, 3.3, 4.3], dtype=object))
这是3个数组的元组。它们可以与stack
:
In [527]: np.stack(_, 1)
Out[527]:
array([[0.1, 0.2, 0.3],
[1.1, 1.2, 1.3],
[2.1, 2.2, 2.3],
[3.1, 3.2, 3.3],
[4.1, 4.2, 4.3]], dtype=object)
我可以使用astype(float)
进一步采取步骤。
我当然认为这是一个玩具功能。对于这个简单的事情,不需要使用vectorize
。
In [528]: fun(np.arange(5))
Out[528]:
(array([ 0.1, 1.1, 2.1, 3.1, 4.1]),
array([ 0.2, 1.2, 2.2, 3.2, 4.2]),
array([ 0.3, 1.3, 2.3, 3.3, 4.3]))
所有vectorize
需要的是otypes
参数:
In [536]: np.vectorize(fun, otypes='ddd')(np.arange(5))
Out[536]:
(array([ 0.1, 1.1, 2.1, 3.1, 4.1]),
array([ 0.2, 1.2, 2.2, 3.2, 4.2]),
array([ 0.3, 1.3, 2.3, 3.3, 4.3]))
如果函数返回数组而不是元组或列表,我们可以使用signature
:
In [546]: def fun(x):
...: return np.array([x+.1, x+.2, x+.3])
In [547]: np.vectorize(fun, signature='()->(n)')(np.arange(5))
Out[547]:
array([[ 0.1, 0.2, 0.3],
[ 1.1, 1.2, 1.3],
[ 2.1, 2.2, 2.3],
[ 3.1, 3.2, 3.3],
[ 4.1, 4.2, 4.3]])
或者使用原始元组/列表大小写,将其包装在lambda np.vectorize(lambda x:np.array(fun(x)), signature='()->(n)')
经验表明frompyfunc
方法最快。带有otypes的vectorize
有点慢(但它使用frompyfunc
)。 signature
是更新的方法,使用不同的代码,速度稍慢。
使用新的func
,signature
方法仍然有效。我添加了excluded
,因此它不会尝试broadcast
n
参数:
In [553]: np.vectorize(lambda x,n:np.array(func(x,n)), signature='()->(n)',excluded=[1])(np.arange(5),3)
Out[553]:
array([[0, 1, 2],
[1, 2, 3],
[2, 3, 4],
[3, 4, 5],
[4, 5, 6]])
In [554]: np.vectorize(lambda x,n:np.array(func(x,n)), signature='()->(n)',excluded=[1])(np.arange(5),7)
Out[554]:
array([[ 0, 1, 2, 3, 4, 5, 6],
[ 1, 2, 3, 4, 5, 6, 7],
[ 2, 3, 4, 5, 6, 7, 8],
[ 3, 4, 5, 6, 7, 8, 9],
[ 4, 5, 6, 7, 8, 9, 10]])