2016-04-10 4 views
0

forループを使用せずに、2つのndarrayの対応する要素に一度の関数を適用したいとします。たとえば、次の2つのndarray xyと、2つの1次元配列をとり、betaを計算する関数fooがあるとします。私が欲しい 最終結果はbeta00 = foo(x[0, 0],y[0])beta01 = foo(x[0, 1], y[1])beta10 = foo(x[1, 0],y[0])beta11 = foo(x[1, 1], y[1])を計算し、私はベクトル化機能に探してきた2つのndarrayの対応する行を一度に(forループなしで)適用する

[[beta00, beta01], 
    [beta10, beta11]] 

の期待される結果をもたらすと機能を適用することで、まだ解決していません。誰かが私にこれを助けることができますか?事前に多くの感謝。

import numpy as np 
x = np.array([[[0, 1, 2, 3], [0, 1, 2, 3]], 
       [[2,3,4,5], [2,3,4,5]]]) 
y = np.array([[-1, 0.2, 0.9, 2.1], [-1, 0.2, 0.9, 2.1]]) 

def foo(x,y): 
    A = np.vstack([x, np.ones(x.shape)]).T 
    return np.linalg.lstsq(A, y)[0][0] 
+0

(x)のところxはタプルとなり、map(foo、zip(x、y))を使用します – Aquiles

+0

共通の2d numpyインデックスを使用すると、コードはより明確になります。 'a [0] 0] '。と 'len(x)'ではなく 'x.shape [0]'となります。言い換えれば、1d、2dなどの配列を持つ場所を明確にしてください。つまり、実際のベクトル化の鍵は多次元配列を受け入れるように 'foo'を書くことです。 – hpaulj

答えて

1

だからfooは2つの1D配列をとり、スカラーを返し

beta[i,j] = foo(x[i,j,:], y[j,:]) 

をしたいです。明示的な:は、3と2の配列を使用していることを明確にしています。

np.vectorizeは、その関数が配列ではなくスカラーを受け入れる必要があるため、役に立たないでしょう。そして、それはスピードの解決策ではありません。放送を可能にし、さまざまな次元の入力を処理するのと同じくらい良い方法です。

ループのラッパーはapply_along(over)_axisですが、それでもPythonレベルのループです。実際のスピードアップの鍵は、fooを改造して、1dのものだけでなく、2または3dアレイで動作するようにすることです。しかしそれはそれが価値あるものよりも多くの仕事をすることも、不可能かもしれません。

だから参考のために、任意の代替は一致している必要があります:

for i,j in np.ndindex(x.shape[:2]): 
    beta[i,j] = foo(x[i,j,:], y[j,:]) 

が、それは時間の節約ではありません。

beta = np.zeros(x.shape[:2]) 
for i in range(x.shape[0]): 
    for j in range(x.shape[1]): 
     beta[i,j] = foo(x[i,j,:],y[j,:]) 

多次元インデックスを生成する別の方法です。

fooは2D yを受け入れるために書くことができるかどうかを調べる、

行うことができるように最終的に目指す
foo(x[i,j,:], y[None,j,:]) 

:あなたはデフFOOとしてあなたのfooを再定義することができ

beta = foo1(x, y[None,:]) 
+0

意味があります。ありがとうございました。しかし、単にnumpyを学習する目的のためには、ここで 'apply_along(over)_axis'をどのように使うべきですか?私は文書を見ましたが、私はまだ少し混乱しています。 – no89key

+0

私は 'apply ...'関数に関する質問に答えましたが、私のコードには使用していません。これらは1つの入力配列だけで動作するように設計されており、2を超える反復を調整しないため、このケースには適合しないことがあります。 – hpaulj

関連する問題