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
方法是最快的。vectorize
使用 otypes 有点慢(但它使用frompyfunc
). signature
是较新的方法,使用不同的代码,并且速度稍慢。
与你的新func
, the signature
方法仍然有效。我添加了excluded
所以它不会尝试broadcast
the 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]])