在返回向量的函数上使用Numpy Vectorize

pro*_*ius 31 python arrays numpy vectorization

numpy.vectorize 取函数f:a-> b并将其变为g:a [] - > b [].

这在标量ab标量时都可以正常工作,但是我想不出为什么它不能用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))
Run Code Online (Sandbox Code Playgroud)

这会产生:

array([[ 0.  0.  0.  0.  0.],
       [ 1.  1.  1.  1.  1.],
       [ 2.  2.  2.  2.  2.],
       [ 3.  3.  3.  3.  3.]], dtype=object)
Run Code Online (Sandbox Code Playgroud)

好的,所以给出了正确的值,但错误的dtype.更糟糕的是:

g(a).shape
Run Code Online (Sandbox Code Playgroud)

收益率:

(4,)
Run Code Online (Sandbox Code Playgroud)

所以这个阵列几乎没用.我知道我可以将其转换为:

np.array(map(list, a), dtype=np.float32)
Run Code Online (Sandbox Code Playgroud)

给我我想要的东西:

array([[ 0.,  0.,  0.,  0.,  0.],
       [ 1.,  1.,  1.,  1.,  1.],
       [ 2.,  2.,  2.,  2.,  2.],
       [ 3.,  3.,  3.,  3.,  3.]], dtype=float32)
Run Code Online (Sandbox Code Playgroud)

但这既不高效也不高潮.你们中的任何人都能找到更清洁的方法吗?

提前致谢!

unu*_*tbu 40

np.vectorize只是一个便利功能.它实际上并没有使代码运行得更快.如果使用起来不方便np.vectorize,只需编写自己的功能即可.

目的np.vectorize是转换不是numpy-aware的函数(例如将float作为输入并将float作为输出返回)到可以操作(并返回)numpy数组的函数中.

你的函数f已经是numpy-aware - 它在其定义中使用了一个numpy数组并返回一个numpy数组.因此np.vectorize不适合您的用例.

因此,解决方案就是按照您f的方式运行您自己的功能.

  • 实际上,"只是一个便利功能"描述了大多数numpy API.这就是重点.太糟糕了,这个功能的表现并不像人们期望的那样. (8认同)
  • 不是根据/sf/ask/2465061301/ (3认同)

Cos*_*syn 10

signature1.12.0中的新参数完全符合您的要求.

def f(x):
    return x * np.array([1,1,1,1,1], dtype=np.float32)

g = np.vectorize(f, signature='()->(n)')
Run Code Online (Sandbox Code Playgroud)

然后g(np.arange(4)).shape会给(4L, 5L).

这里f指定了签名.它(n)是返回值()的形状,是标量参数的形状.参数也可以是数组.有关更复杂的签名,请参阅通用通用函数API.


小智 5

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)
b = g(a)
b = np.array(b.tolist())
print(b)#b.shape = (4,5)
c = np.ones((2,3,4))
d = g(c)
d = np.array(d.tolist())
print(d)#d.shape = (2,3,4,5)
Run Code Online (Sandbox Code Playgroud)

这应该可以解决该问题,并且无论输入大小如何,它都可以工作。“地图”仅适用于一个三维输入。使用“ .tolist()”并创建一个新的ndarray可以更完全,更好地解决该问题(我相信)。希望这可以帮助。