2016-05-06 9 views
0

n x mの行列があり、それぞれの要素に関数fctを呼び出すとします。私はそれが好き行うことができます。Numpyの各行の `vectorize`

A = numpy.array(...) 
vec_func = numpy.vectorize(fct) 
A_out = vec_func(A) 

これは厳密にはFCT機能になり、行列の各要素に関数を適用します:今、私は同じことを希望

def fct(a_ij): 
    # do something with matrix element a(i, j) 

が、それぞれのマトリクスの行:

def fct(row_i): 
    # do something with matrix row(i) 

numpy.vectorizeまたは類似の方法で行うことはできますか?

+2

私はちょうど読んでいます: "vectorize関数は、パフォーマンスのためではなく便宜上提供されています。実装は本質的にforループです。"とにかくその機能はそれほど有用ではありません。 – Michael

+3

ベクトル化には "機能にとらわれない"方法がありません。これはパフォーマンスを大幅に向上させます( 'np.vectorize'は文法上の砂糖です)。入力引数として配列を受け入れるために 'fct'を書き換えることも、コンパイルされた実装(例えばCython、numba)に切り替えることもできます。 –

+0

@ ali_mの提案に追加するには、numbaの一般化されたufunc http://numba.pydata.org/numba-doc/dev/user/vectorize.html#the-guvectorize-Decoratorを試してみてください。速度の向上を除けば、それはあなたが望むインテリジェントなブロードキャストを行います。 – DavidW

答えて

1

編集:それはnp.apply_along_axisのように見えます。例:

import numpy as np 

def f(x): 
    return x * x.sum() 

X = np.arange(12).reshape(2, 2, 3) 
np.apply_along_axis(f, -1, X) 
# array([[[ 0, 3, 6], 
#   [ 36, 48, 60]], 
# 
#  [[126, 147, 168], 
#   [270, 300, 330]]]) 

以下の元の応答のパフォーマンスに関する注意事項が引き続き適用されます。


オリジナルの応答:

そこにはビルトインこのためませんが、Pythonは、このようなコンテキストマネージャを自分で定義することは簡単になります。

import numpy as np 
from contextlib import wraps 

def row_vectorize(f): 
    @wraps(f) 
    def wrapped_f(X): 
     X = np.asarray(X) 
     rows = X.reshape(-1, X.shape[-1]) 
     return np.reshape([f(row) for row in rows], 
          X.shape[:-1] + (-1,)) 
    return wrapped_f 


@row_vectorize 
def func(row): 
    return row * row.sum() 

今、あなたは、任意の非ゼロ次元の配列にこれを使用することができます:たとえば

>>> X_1D = np.arange(3) 
>>> func(X_1D) 
array([0, 3, 6]) 

>>> X_2D = np.arange(6).reshape(2, 3) 
>>> func(X_2D) 
array([[ 0, 3, 6], 
     [36, 48, 60]]) 

>>> X_3D = np.arange(12).reshape((2, 2, 3)) 
>>> func(X_3D) 
array([[[ 0, 3, 6], 
     [ 36, 48, 60]], 

     [[126, 147, 168], 
     [270, 300, 330]]]) 

は、性能面、np.vectorizeは非常に似た何かをやっています。

配列全体に適用されるカスタム関数のループを高速化する必要がある場合は、numpyの要素ごとの操作と集計操作の点でメソッドを構築することができます。あなたがより複雑な操作を持っている場合は、配列の行全体に適用したいと思います

def func2(X): 
    return X * X.sum(-1, keepdims=True) 

:たとえば、この関数は、上の行ベクトル化機能と同じことを実現しますが、大入力にはるかに高速になりますループのパフォーマンスがボトルネックである場合、最良のオプションはおそらくnumbaまたはcythonを使用することです。

関連する問題