2016-03-22 30 views
0

我想对5x1 numpy数组的每一行应用一个函数。我正在应用的函数有两个参数,我希望数组的元素作为第二个参数输入,而不是第一个参数。我一直在使用numpy.apply_along_axis()。看看这个功能的文档,看起来好像不太可能。在numpy.apply_along_axis的参数顺序

有没有办法做到这一点,而没有明确定义一个新的函数与颠倒的参数顺序?我只是好奇。这是我一直在搞的例子。

import numpy as np 
tmp = np.random.rand(5,1) 
lol = lambda first, second: float(first)/second 
print tmp 
np.apply_along_axis(lol, 1, tmp, second=1) #works but I don't want this 
np.apply_along_axis(lol, 1, tmp, first=1) # doesn't work 

回答

1

我要调整你的例子,使其更有趣一些

In [188]: tmp=np.arange(6.).reshape(2,3) 
In [189]: lol=lambda first, second: np.sum(first)/second 

因此,与2D tmp中,我们可以沿着任一轴应用它

In [190]: np.apply_along_axis(lol,0,tmp,2) 
Out[190]: array([ 1.5, 2.5, 3.5]) 

In [191]: np.apply_along_axis(lol,1,tmp,2) 
Out[191]: array([ 1.5, 6. ]) 

另一个lambda干净切换参数:

In [192]: np.apply_along_axis(lambda x,y:lol(y,x),0,tmp,2) 
Out[192]: 
array([[  inf, 2.  , 1.  ], 
     [ 0.66666667, 0.5  , 0.4  ]]) 

(与2/tmp相同; axis does not ma tter)

函数调用的额外层不会改变执行速度太多(切换参数会增加时间,但我想关注额外lambda的影响)。

In [195]: timeit np.apply_along_axis(lol,1,tmp,2) 
10000 loops, best of 3: 103 us per loop 

In [196]: timeit np.apply_along_axis(lambda x,y:lol(x,y),1,tmp,2) 
10000 loops, best of 3: 105 us per loop 

关于使用apply_along_axis没有什么不可思议的或特别有效的;你(或我们)可以写一个迭代来做同样的事情。

让我们来比较2倍的表达,一个apply_along_axis和等价列表理解:

In [213]: np.apply_along_axis(lol,0,tmp,2) 
Out[213]: array([ 1.5, 2.5, 3.5]) 

In [214]: np.array([lol(tmp[:,i],2) for i in range(tmp.shape[1])]) 
Out[214]: array([ 1.5, 2.5, 3.5]) 

In [215]: timeit np.apply_along_axis(lol,0,tmp,2) 
10000 loops, best of 3: 132 us per loop 

In [217]: timeit np.array([lol(tmp[:,i],2) for i in range(tmp.shape[1])]) 
10000 loops, best of 3: 64.1 us per loop 

apply_along_axis比较慢,可能是因为它正试图更加普遍。这可能更方便,但它并不明显更“有效”。

0

这是可能的!但是函数本身与数据作为第一个参数(见source)直接调用,所以你需要另一个抽象层来改变参数:有一个装饰,例如:

from functools import wraps 
def swapelements(func): 
    @wraps(func) 
    def wrapper(array, *args, **kwargs): 
     # Insert the array as second=array: 
     kwargs['second'] = array 
     return func(*args, **kwargs) 
    return wrapper 

np.apply_along_axis(swapelements(lol), 1, tmp, first=1) 
 
array([[ 6.24582532], 
     [ 1.14800413], 
     [ 1.87634432], 
     [ 14.31209963], 
     [ 2.47123623]]) 

tmp[[ 0.16010694], [ 0.871077 ], [ 0.53295122], [ 0.06987095], [ 0.40465577]]


如果一个5x1阵列上运行你为什么要使用apply_along_axis?您可以通过以下方式实现:

result = 1./tmp 

您的第二轴只包含一个元素。