np.apply_along_axis返回多个值

时间:2019-06-06 11:14:38

标签: python numpy dictionary lambda

我正在将一些函数应用于numpy数组。

import numpy as np
MATRIX=np.random.rand(5,7)


def F_a(x):
   return 1

def F_b(x):
   return [1,2]
FUNCS=[F_a,F_b]

results=list(map(lambda f:np.apply_along_axis(f,1, MATRIX),FUNCS))

当所有FUNCS返回一个标量值时,它就会按预期工作。 但是,我的FUNC中有一些返回可迭代项(例如,可变长度列表)。

如何应用以这种方式返回多个值的函数(地图+ apply_along_axis)?

如果运行MVE,则会得到:

[array([1, 1, 1, 1, 1]), array([[1, 2],
        [1, 2],
        [1, 2],
        [1, 2],
        [1, 2]])]

我想要的输出将是一个大小为5x3的单个数组,而不是两个数组5x1和5x2

如果我尝试:

results=np.stack(list(map(lambda f:np.apply_along_axis(f,1, MATRIX),FUNCS)))

我得到:

ValueError: all input arrays must have the same shape

np.vstacknp.hstack

1 个答案:

答案 0 :(得分:1)

使用轴1和2d输入,apply_along_axis仅对行(其他维)进行迭代,并返回其形状由迭代维和函数值确定的数组。

如果fn返回标量,则结果仅为(5,),即行的大小:

In [291]: np.apply_along_axis(lambda a1: 1, 1,arr)                                                     
Out[291]: array([1, 1, 1, 1, 1])
In [292]: _.shape                                                                                      
Out[292]: (5,)

如果返回列表或单个元素数组,则该维的大小为1:

In [293]: np.apply_along_axis(lambda a1: [1], 1,arr)                                                   
Out[293]: 
array([[1],
       [1],
       [1],
       [1],
       [1]])
In [294]: _.shape                                                                                      
Out[294]: (5, 1)

以此类推获得其他回报:

In [295]: np.apply_along_axis(lambda a1: np.arange(4), 1,arr)                                          
Out[295]: 
array([[0, 1, 2, 3],
       [0, 1, 2, 3],
       [0, 1, 2, 3],
       [0, 1, 2, 3],
       [0, 1, 2, 3]])
In [296]: _.shape                                                                                      
Out[296]: (5, 4)
In [297]: np.apply_along_axis(lambda a1: a1, 1,arr)                                                    
Out[297]: 
array([[0., 0., 0.],
       [0., 0., 0.],
       [0., 0., 0.],
       [0., 0., 0.],
       [0., 0., 0.]])
In [298]: _.shape                                                                                      
Out[298]: (5, 3)

这与通过列表理解构建数组相同:

In [302]: [(lambda a1:1)(row) for row in arr]                                                          
Out[302]: [1, 1, 1, 1, 1]
In [303]: [(lambda a1:[1,2])(row) for row in arr]                                                      
Out[303]: [[1, 2], [1, 2], [1, 2], [1, 2], [1, 2]]

使用apply_along_axis这样的2d输入仅是一种符号上的方便。对于较大的尺寸,便利性更大。但这并不能通过更直接的迭代来提高速度。

如果您不了解apply_along_axis或在使用它时遇到问题,请不要打扰。进行您了解的那种迭代。

====

如果

def F_a(x):
    return [1]

您的列表图将产生(5,1)和(5,2)数组,然后可以将它们连接在第二轴上。

因此,除了apply遇到问题外,您似乎对numpy数组维及其如何控制concatenate(以及各种{{1 }}变体。