私は4次元配列を持っていますが、最後の2次元を反復して2次元スライスを作成する関数を適用したいと思います。 Vizは(x、y、0,0)にf(2d_array)を、(x、y、0,1)などにf(2d_array)を適用します。同じであるが、一般的な解は、形状の配列(x '、y'、w、z)を返す。ここでwとzは元の配列の最後の2つの次元である。numpyはn個の空白に沿って適用します
これは明らかにnDアレイ上のmDスライスに一般化できます。
このことを行う組み込みの機能はありますか?
私は4次元配列を持っていますが、最後の2次元を反復して2次元スライスを作成する関数を適用したいと思います。 Vizは(x、y、0,0)にf(2d_array)を、(x、y、0,1)などにf(2d_array)を適用します。同じであるが、一般的な解は、形状の配列(x '、y'、w、z)を返す。ここでwとzは元の配列の最後の2つの次元である。numpyはn個の空白に沿って適用します
これは明らかにnDアレイ上のmDスライスに一般化できます。
このことを行う組み込みの機能はありますか?
「基本」適用-に沿って軸モデルは一つの軸に反復し、あなたの関数に他を渡すことです:
In [197]: def foo(x): # return same size
...: return x*2
...: np.array([foo(x) for x in np.arange(12).reshape(3,4)])
...:
Out[197]:
array([[ 0, 2, 4, 6],
[ 8, 10, 12, 14],
[16, 18, 20, 22]])
In [198]: def foo(x):
...: return x.sum() # return one less dim
...: np.array([foo(x) for x in np.arange(12).reshape(3,4)])
...:
Out[198]: array([ 6, 22, 38])
In [199]: def foo(x):
...: return x.sum(keepdims=True) # condense the dim
...: np.array([foo(x) for x in np.arange(12).reshape(3,4)])
...:
Out[199]:
array([[ 6],
[22],
[38]])
あなたの4Dの問題は、これを合わせてマッサージすることができます。行うのと等価である
In [200]: arr_4d = np.arange(24).reshape(2,3,2,2)
In [201]: arr_2d = arr_4d.reshape(6,4).T
In [202]: res = np.array([foo(x) for x in arr_2d])
In [203]: res
Out[203]:
array([[60],
[66],
[72],
[78]])
In [204]: res.reshape(2,2)
Out[204]:
array([[60, 66],
[72, 78]])
:
In [205]: arr_4d[:,:,0,0].sum()
Out[205]: 60
In [206]: foo(arr_4d[:,:,0,0].ravel())
Out[206]: array([60])
apply_along_axis
は1Dアレイを取る機能を必要とするが、このようにして適用することができる。
In [209]: np.apply_along_axis(foo,0,arr_4d.reshape(6,2,2))
Out[209]:
array([[[60, 66],
[72, 78]]])
foo
はにその入力を作り直すことができ2dをとり、2dをとる関数に渡します。 apply_along_index
は、反復軸のインデックスを生成するためにnp.ndindex
を使用します。
In [212]: list(np.ndindex(2,2))
Out[212]: [(0, 0), (0, 1), (1, 0), (1, 1)]
np.vectorize
は、通常、スカラーを取る関数で動作します。しかし、最近のバージョンにはsignature
というパラメータがあります。これはあなたのケースを扱うために使うことができると思います。それは最初の2つの軸を反復し、最後の2つを関数に渡すように入力を転置する必要があります。私の答えはhttps://stackoverflow.com/a/46004266/901925です。これらのアプローチの
なし速度の利点を提供しています。整形またはスワップなし
、私はndindex
の助けを借りて繰り返すことができます。
は、2D入力を期待する関数を定義します:arr_4d
の最後の2薄暗いため
def foo2(x):
return x.sum(axis=1, keepdims=True) # 2d
インデックス反復子:
In [260]: idx = np.ndindex(arr_4d.shape[-2:])
は、リターンの形状を決定するためにテストCALCを行います。 vectorize
とapply...
この種のテストを行います。
In [261]: r1 = foo2(arr_4d[:,:,0,0]).shape
In [262]: r1
Out[262]: (2, 1)
結果配列:
In [263]: res = np.zeros(r1+arr_4d.shape[-2:])
In [264]: res.shape
Out[264]: (2, 1, 2, 2)
今反復:
In [265]: for i,j in idx:
...: res[...,i,j] = foo2(arr_4d[...,i,j])
...:
In [266]: res
Out[266]:
array([[[[ 12., 15.],
[ 18., 21.]]],
[[[ 48., 51.],
[ 54., 57.]]]])
numpy.apply_over_axes
のようなものを探して、for
のループを組み合わせて、さまざまな軸を繰り返し処理していると思います。
私は自分の圧延。私は、これと@ hpauljの方法の間にパフォーマンスの違いがあるかどうか、またカスタムcモジュールを書くことが重要な改善をもたらすと信じる理由があるかどうかを知ることに興味があります。もちろん、@ hpauljのメソッドはより一般的です。なぜなら、これは配列の操作をただちに実行する必要があるからです。
def apply_along_space(f, np_array, axes):
# apply the function f on each subspace given by iterating over the axes listed in axes, e.g. axes=(0,2)
for slic in itertools.product(*map(lambda ax: range(np_array.shape[ax]) if ax in axes else [slice(None,None,None)], range(len(np_array.shape)))):
f(np_array[slic])
return np_array
すべてのドキュメントを確認しましたか? – wwii