2016-03-22 66 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 

您的第二軸只包含一個元素。