当函数返回高维数组时,怎么做numpy apply_along_axis?

时间:2016-10-21 05:29:57

标签: numpy

我有一个形状(10, 100000)和一个函数f的数组,它将形状(100000,)的数组转换为形状(200,200)的数组。将f应用于10行中的每一行以获得形状数组的最简单方法是什么 (10,200,200)?我希望使用apply_along_axis,但它似乎不起作用,因为f的输出的维度高于输入的维度。

(更一般地说,给定形状a的数组(x1,...,xn,y1,...,ym)和函数f,它将形状(y1,...,ym)的数组转换为形状(z1,...,zp)的数组,您可能希望将f应用于m的最后a维度,对于n的第一个a维度的每个设置,以获取形状(x1,...,xn,z1,...,zp)。或者你可能有一个问题可以转换成这种形式之一。做这些转换的最佳方法是什么?)

1 个答案:

答案 0 :(得分:1)

我的第一个想法是重塑a,将第一个n尺寸折叠为一个。然后,只需迭代该维度,将f应用于每个子阵列。将结果收集到列表(或正确大小的数组)中。最后重塑。

正如您所描述的那样,x1...xn尺寸只是为了骑行。

查看apply_along_axis的代码。它迭代所有轴,除了传递给函数的轴。它没有做任何你可以用你自己的迭代做的事情。它会处理x1...xn上的迭代,但需要将y维度折叠为1,并且需要一个返回相同形状的函数。

该功能的核心是

res = func1d(arr[tuple(i.tolist())], *args, **kwargs)
outarr[tuple(ind)] = res

其中outarr已初始化为正确的大小,ind会跨越所有维度(除了一个)。它有一个slice对象res

=====================

以2d输入数组开头的简单示例:

In [933]: def foo(arr):
     ...:     return arr.reshape(2,-1)
     ...: 
In [934]: source=np.arange(12).reshape(3,4)
In [935]: dest=np.zeros((source.shape[0],2,2),source.dtype)
In [936]: for i,r in enumerate(source):
     ...:     dest[i,...] = foo(r)
     ...:     
In [937]: dest
Out[937]: 
array([[[ 0,  1],
        [ 2,  3]],

       [[ 4,  5],
        [ 6,  7]],

       [[ 8,  9],
        [10, 11]]])

因此,这将迭代源的行,生成新数组,并将它们插入到目标的正确位置。要设置目的地,我必须知道foo生成的内容(维度)。

列表附加方法并不需要太多的知识:

In [938]: dest=[]
In [939]: for i,r in enumerate(source):
     ...:     dest.append(foo(r))    
In [940]: dest
Out[940]: 
[array([[0, 1],
        [2, 3]]), array([[4, 5],
        [6, 7]]), array([[ 8,  9],
        [10, 11]])]
In [941]: np.array(dest)
...

归结为旧问题,'如何从函数生成新数组?'