2016-04-03 23 views
3

データ配列があり、形状は100x100です。私はそれを5x5ブロックに分割し、各ブロックには20x20グリッドがあります。私が望む各ブロックの値は、その中のすべての値の合計です。配列ブロック内の値の合計を評価する方法

これを実現するにはよりエレガントな方法がありますか?

x = np.arange(100) 
y = np.arange(100) 
X, Y = np.meshgrid(x, y) 
Z = np.cos(X)*np.sin(Y) 
Z_new = np.zeros((5, 5)) 
for i in range(5): 
    for j in range(5): 
    Z_new[i, j] = np.sum(Z[i*20:20+i*20, j*20:20+j*20]) 

これはインデックスに基づいています。

x = np.linspace(0, 1, 100) 
y = np.linspace(0, 1, 100) 
X, Y = np.meshgrid(x, y) 
Z = np.cos(X)*np.sin(Y) 
x_new = np.linspace(0, 1, 15) 
y_new = np.linspace(0, 1, 15) 

Z_new?

+0

任意の数のディメンションのソリューション:http://stackoverflow.com/questions/36269508/lets-make-a-reference-implementation-of-n-dimensional-pixel-binning-bucketing-f/36269734#36269734 –

+0

@ajcr重複したリンクされた質問には、このようなケースを解決するために必要ではない一般的なndarrayのケースを設定することにかなりのオーバーヘッドが伴うため、これを再開します。これは大丈夫だと思う。 – Divakar

答えて

3

次いで形状(5,20)とを有する2つのそれぞれに単純reshape分割それら二つの軸のそれぞれにそうように、長さを20を有する軸に沿って低減合計 -

Z_new = Z.reshape(5,20,5,20).sum(axis=(1,3)) 

機能的には同じ、しかしnp.einsumと潜在的に速いオプション -

Z_new = np.einsum('ijkl->ik',Z.reshape(5,20,5,20)) 

ランタイムテスト -

In [18]: x = np.arange(100) 
    ...: y = np.arange(100) 
    ...: X, Y = np.meshgrid(x, y) 
    ...: Z = np.cos(X)*np.sin(Y) 
    ...: 

In [19]: %timeit Z.reshape(5,20,5,20).sum(axis=(1,3)) 
10000 loops, best of 3: 49.5 µs per loop 

In [20]: %timeit np.einsum('ijkl->ik',Z.reshape(5,20,5,20)) 
10000 loops, best of 3: 46.7 µs per loop 
0

以下の操作を行うことができます。

t = np.eye(5).repeat(20, axis=1) 
Z_new = t.dot(Z).dot(t.T) 

Z_new[i, j] = t[i, k] * Z[k, l] * t[j, l]

はまた、これはDivakarのソリューションよりも速いようですので、これは正しいです。

0

このような問題は、「グループ化」と「ラベリング」という用語を使用できるため、scipy.ndimage.measurements.sumのような機能の非常に良い候補です。

labels = [[20*(y//5) + x//5 for x in range(100)] for y in range(100)] 
s = scipy.ndimage.measurements.sum(Z, labels, range(400)) 

(テストされていないが、それはアイデアです):あなたはのようなものと欲しいものを持っています。