numpy vectorize维度增加函数

时间:2018-01-26 15:54:05

标签: python numpy

我想创建一个输入为x.shape==(2,2)的函数,并输出y.shape==(2,2,3)

例如:

@np.vectorize
def foo(x):
  #This function doesn't work like I want
  return x,x,x

a = np.array([[1,2],[3,4]])
print(foo(a))
#desired output
[[[1 1 1]
  [2 2 2]]

 [[3 3 3]
  [4 4 4]]]

#actual output
(array([[1, 2],
   [3, 4]]), array([[1, 2],
   [3, 4]]), array([[1, 2],
   [3, 4]]))

或者也许:

@np.vectorize
def bar(x):
  #This function doesn't work like I want
  return np.array([x,2*x,5])

a = np.array([[1,2],[3,4]])
print(bar(a))
#desired output
[[[1 2 5]
  [2 4 5]]

 [[3 6 5]
  [4 8 5]]]

请注意foo只是一个例子。我想要一个方法map超过一个numpy数组(这是vectorize应该做的),但让map获取一个0d对象并在其位置推送一个1d对象。在我看来,这里的维度是任意的,因为人们可能希望采用一个函数来获取1d对象并返回一个3d对象,对其进行矢量化,在5d对象上调用它,然后返回一个7d对象......但是,我的特定用例只需要向量化0d到1d函数,并在2d数组上正确映射它。

3 个答案:

答案 0 :(得分:2)

将值重复到另一个维度非常简单:

import numpy as np

x = a = np.array([[1,2],[3,4]])
y = np.repeat(x[:,:,np.newaxis], 3, axis=2)
print y.shape
print y


(2L, 2L, 3L)
[[[1 1 1]
  [2 2 2]]

 [[3 3 3]
  [4 4 4]]]

答案 1 :(得分:2)

在您的问题中,显示实际结果和您想要的结果会有所帮助。正如所写,不是很清楚。

In [79]: foo(np.array([[1,2],[3,4]]))
Out[79]: 
(array([[1, 2],
        [3, 4]]), array([[1, 2],
        [3, 4]]), array([[1, 2],
        [3, 4]]))

vectorize文档中所示,这返回了一个数组元组,对应于函数返回的元组值。

您的bar会返回一个数组,其中vectorize期望它返回一个标量(或单个值):

In [82]: bar(np.array([[1,2],[3,4]]))
ValueError: setting an array element with a sequence.

vectorize采用有时有帮助的otypes参数。例如,如果我说bar(没有包装器)返回一个对象,我得到:

In [84]: f=np.vectorize(bar, otypes=[object])

In [85]: f(np.array([[1,2],[3,4]]))
Out[85]: 
array([[array([1, 2, 5]), array([2, 4, 5])],
       [array([3, 6, 5]), array([4, 8, 5])]], dtype=object)

(3)数组的(2,2)数组。 (2,2)形状与输入的形状相匹配。

vectorize有一个相对较新的参数signature

In [90]: f=np.vectorize(bar, signature='()->(n)')

In [91]: f(np.array([[1,2],[3,4]]))
Out[91]: 
array([[[1, 2, 5],
        [2, 4, 5]],

       [[3, 6, 5],
        [4, 8, 5]]])
In [92]: _.shape
Out[92]: (2, 2, 3)

我还没有使用过这么多,所以我仍然对它的运作方式有所了解。当我测试它时,它比vectorize的原始标量版本慢。两者都没有提供显式循环的任何速度优势。但是,vectorize在广播时会有所帮助,允许您使用各种输入形状。当你的函数接受多个输入时,这更有用,而不仅仅是一个输入。

In [94]: f(np.array([1,2]))
Out[94]: 
array([[1, 2, 5],
       [2, 4, 5]])

In [95]: f(np.array(3))
Out[95]: array([3, 6, 5])

为了获得最佳速度,您希望尽可能使用现有的numpy全数组函数。例如,您的foo案例可以通过以下方式完成:

In [97]: np.repeat(a[:,:,None],3, axis=2)
Out[97]: 
array([[[1, 1, 1],
        [2, 2, 2]],

       [[3, 3, 3],
        [4, 4, 4]]])

np.stack([a]*3, axis=2)也有效。

您的bar期望结果:

In [100]: np.stack([a, 2*a, np.full(a.shape, 5)], axis=2)
Out[100]: 
array([[[1, 2, 5],
        [2, 4, 5]],

       [[3, 6, 5],
        [4, 8, 5]]])

2*a利用了整数组乘法。这是真正的&numpy-onic'思。

答案 2 :(得分:0)

这似乎适用于" f R0 - > R1映射到nd数组,给出(n + 1)d one"

def foo(x):
  return np.concatenate((x,x))
np.apply_along_axis(foo,2,x.reshape(list(x.shape)+[1]))
尽管

并没有很好地概括这一切