通常,np.vectorize用于将标量(Python非numpy)函数应用于数组的所有元素或数组。还有那往往忽略了一个注:主要是为了方便而提供

的vectorize功能,而不是 性能。实现本质上是一个for循环。

In [278]: m = np.array([[1,2,3],[4,5,6]])

In [279]: np.vectorize(lambda x:2*x)(m)

Out[279]:

array([[ 2, 4, 6],

[ 8, 10, 12]])

这乘以2的m每个元素,照顾循环纸工作的我们。

更好的是,当给定几个数组时,它会广播('外部产品'的泛化)。

In [280]: np.vectorize(lambda x,y:2*x+y)(np.arange(3), np.arange(2)[:,None])

Out[280]:

array([[0, 2, 4],

[1, 3, 5]])

这馈送(x,y)标量元组拉姆达用于广播的针对(2,1)阵列(3)阵列的所有组合,产生了(2,3)阵列。它可以被看作是广播的map的扩展。

np.vectorize(np.rot90)的问题是rot90需要一个2d数组,但是vectorize将为其提供标量。

但是我在文档中看到,对于v1.12他们已经添加了签名参数。这是我第一次使用它。

你的问题 - 应用np.rot90到三维数组的2D元素:

In [266]: m = np.array([[1,2,3],[4,5,6]])

In [267]: a = np.stack([m,m])

In [268]: a

Out[268]:

array([[[1, 2, 3],

[4, 5, 6]],

[[1, 2, 3],

[4, 5, 6]]])

虽然你可以描述这个a为二维数组的数组,最好是把它当作一个整数三维阵列。这就是np.vectorize(myfun)(a)看到它,给每个号码myfun。

应用到2D m:

In [269]: np.rot90(m)

Out[269]:

array([[3, 6],

[2, 5],

[1, 4]])

使用Python工作的马,在列表理解:

In [270]: [np.rot90(i) for i in a]

Out[270]:

[array([[3, 6],

[2, 5],

[1, 4]]), array([[3, 6],

[2, 5],

[1, 4]])]

结果是一个列表,但我们可以换,在np.array。

Python map做同样的事情。

In [271]: list(map(np.rot90, a))

Out[271]:

[array([[3, 6],

[2, 5],

[1, 4]]), array([[3, 6],

[2, 5],

[1, 4]])]

理解和映射都在结果2d元素上的a,action的第1维上迭代。

vectorizesignature用:

In [272]: f = np.vectorize(np.rot90, signature='(n,m)->(k,l)')

In [273]: f(a)

Out[273]:

array([[[3, 6],

[2, 5],

[1, 4]],

[[3, 6],

[2, 5],

[1, 4]]])

的signature告诉它传递一个二维数组,并期望背面的2D阵列。 (我应该探讨如何signature扮演与otypes参数。)

一些快速的时间比较:

In [287]: timeit np.array([np.rot90(i) for i in a])

10000 loops, best of 3: 40 µs per loop

In [288]: timeit np.array(list(map(np.rot90, a)))

10000 loops, best of 3: 41.1 µs per loop

In [289]: timeit np.vectorize(np.rot90, signature='(n,m)->(k,l)')(a)

1000 loops, best of 3: 234 µs per loop

In [290]: %%timeit f=np.vectorize(np.rot90, signature='(n,m)->(k,l)')

...: f(a)

...:

1000 loops, best of 3: 196 µs per loop

因此,对于一小阵,Python的list方法更快,通过颇有几分。有时候,numpy方法对于更大的阵列会更好,尽管我在这种情况下怀疑。

rot90与轴的参数,甚至更好,而且会具有较大的阵列做的很好:

In [292]: timeit np.rot90(a,axes=(1,2))

100000 loops, best of 3: 15.7 µs per loop

望着np.rot90代码,我看到,它只是做np.flip(反向)和np.transpose,在各种组合取决于k。在这种情况下,效果是这样做的:

In [295]: a.transpose(0,2,1)[:,::-1,:]

Out[295]:

array([[[3, 6],

[2, 5],

[1, 4]],

[[3, 6],

[2, 5],

[1, 4]]])

(这是速度甚至比rot90)

我怀疑vectorize与signature正在做这样的事情:

In [301]: b = np.zeros(2,dtype=object)

In [302]: b[...] = [m,m]

In [303]: f = np.frompyfunc(np.rot90, 1,1)

In [304]: f(b)

Out[304]:

array([array([[3, 6],

[2, 5],

[1, 4]]),

array([[3, 6],

[2, 5],

[1, 4]])], dtype=object)

np.stack(f(b))会将对象数组转换为像其他代码一样的3d数组。

frompyfunc是vectorize的基础函数,并返回一个对象数组。在这里我创建一个像你的a这样的数组,除了它是1d,包含多个m数组。它是一个数组数组,而不是一个3d数组。