2016-03-22 35 views
0

5x1 numpy配列の各行に関数を適用したいと考えています。私が適用している関数は2つの引数をとり、配列の要素を最初の引数ではなく2番目の引数として入力したいと思います。私は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 [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と同じ;軸は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の使用についての効率的な余分なものは何もありません。あなた(または私たち)は同じことをする繰り返しを書くことができます。より一般的になろうとしているためと考え

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、遅い:

apply_along_axisと同等のリスト内包表記は、の2式を比較してみましょう。それはより便利かもしれませんが、明らかにより効率的ではありません。

0

可能です!例えばデコレータで:

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があることをあなたが引数を変更するには、抽象化の別の層を必要とするので、しかし、関数自体は、データが最初の引数(sourceを参照)であることを直接呼び出されます[[ 0.16010694], [ 0.871077 ], [ 0.53295122], [ 0.06987095], [ 0.40465577]]


あなたがapply_along_axisを使用しない理由5x1アレイ上で動作している場合?

result = 1./tmp 

2番目の軸には1つの要素のみが含まれています。私たちはいずれかの軸に沿って、それを適用することができ、2D TMPと

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

だから、もう少し面白くするためにあなたの例を微調整するつもりだ