2

によって通常返される対角線に直交する対角線に沿って反復する次のコードがありますnp.diagonal。位置(0、0)から始まり、右下の座標に向かって進みます。

コードは意図したとおりに機能しますが、すべてのループがあまり複雑ではなく、トリックを実行するために多くの配列を作成する必要があるという点で非効率的です。

だから、これを行うためのより良い方法があるかどうか疑問に思います。なぜなら、配列をストライドする方法や、numpyの対角法を使用してより良い方法でそれを行う方法がわからないからです(失敗するトリックがいくつかあると思いますが)見る)。

import numpy as np

A = np.zeros((4,5))

#Construct a distance array of same size that uses (0, 0) as origo
#and evaluates distances along first and second dimensions slightly
#differently so that no values in the array is the same
D = np.zeros(A.shape)
for i in range(D.shape[0]):
    for j in range(D.shape[1]):
        D[i, j] = i * (1 + 1.0 / (grid_shape[0] + 1)) + j

print D
#[[ 0.          1.          2.          3.          4.        ]
# [ 1.05882353  2.05882353  3.05882353  4.05882353  5.05882353]
# [ 2.11764706  3.11764706  4.11764706  5.11764706  6.11764706]
# [ 3.17647059  4.17647059  5.17647059  6.17647059  7.17647059]]

#Make a flat sorted copy
rD = D.ravel().copy()
rD.sort()

#Just to show how it works, assigning incrementing values
#iterating along the 'orthagonal' diagonals starting at (0, 0) position
for i, v in enumerate(rD):

    A[D == v] = i

print A
#[[ 0  1  3  6 10]
# [ 2  4  7 11 14]
# [ 5  8 12 15 17]
# [ 9 13 16 18 19]]

編集

明確にするために、全体を要素ごとに繰り返しますAが、上記のコードが呼び出す順序で繰り返します(これはfinalに表示されますprint)。

反復が対角線に沿って進む方向(1と2が入れ替わった場合、および3と5などA)は、対角線がAの主対角線(によって生成されたものnp.diag(A))に直交することだけが重要です。

この質問の適用/理由は、私の前の質問(その質問の下部にある解決策の部分)にあります:候補の潜在的に不完全なリストから2Dグリッドを構築する

4

3 に答える 3

4

Python の for ループを回避する方法を次に示します。

まず、加算テーブルを見てみましょう。

import numpy as np
grid_shape = (4,5)
N = np.prod(grid_shape)

y = np.add.outer(np.arange(grid_shape[0]),np.arange(grid_shape[1]))
print(y)

# [[0 1 2 3 4]
#  [1 2 3 4 5]
#  [2 3 4 5 6]
#  [3 4 5 6 7]]

重要なアイデアは、加算テーブルの合計を順番に参照すると、配列を目的の順序で反復処理することになるということです。

を使用して、その注文に関連付けられたインデックスを見つけることができますnp.argsort

idx = np.argsort(y.ravel())
print(idx)
# [ 0  1  5  2  6 10  3  7 11 15  4  8 12 16  9 13 17 14 18 19]

idxゴールデンです。2D 配列は 1D 配列を変形しただけなので、形状 (4,5) の 2D 配列を反復処理するために必要なものは基本的にすべてです。

最終的な目標が投稿の最後に示した配列を生成することである場合は、次のように再度A使用できます。argsort

print(np.argsort(idx).reshape(grid_shape[0],-1))
# [[ 0  1  3  6 10]
#  [ 2  4  7 11 14]
#  [ 5  8 12 15 17]
#  [ 9 13 16 18 19]]

または、代わりに、他の値を に割り当てる必要がある場合はA、おそらくこれがより便利です。

A = np.zeros(grid_shape)
A1d = A.ravel()
A1d[idx] = np.arange(N)  # you can change np.arange(N) to any 1D array of shape (N,)
print(A)
# [[  0.   1.   3.   6.  10.]
#  [  2.   4.   7.  11.  15.]
#  [  5.   8.  12.  16.  18.]
#  [  9.  13.  14.  17.  19.]]

配列を反復処理する方法を求められたことは知っていますが、上記のように配列全体の代入または numpy 関数呼び出し (np.argsort など) を使用して配列を生成すると、おそらく Python ループを使用するよりも高速になるため、上記を示したいと思いました。 . ただし、Python ループを使用する必要がある場合は、次のようにします。

for i, j in enumerate(idx):
   A1d[j] = i

print(A)
# [[  0.   1.   3.   6.  10.]
#  [  2.   4.   7.  11.  15.]
#  [  5.   8.  12.  16.  18.]
#  [  9.  13.  14.  17.  19.]]
于 2013-01-10T13:31:46.617 に答える
3
>>> D
array([[ 0,  1,  2,  3,  4],
       [ 5,  6,  7,  8,  9],
       [10, 11, 12, 13, 14],
       [15, 16, 17, 18, 19]]) 

>>> D[::-1].diagonal(offset=1)
array([16, 12,  8,  4])
>>> D[::-1].diagonal(offset=-3)
array([0])
>>> np.hstack([D[::-1].diagonal(offset=-x) for x in np.arange(-4,4)])[::-1]
array([ 0,  1,  5,  2,  6, 10,  3,  7, 11, 15,  4,  8, 12, 16,  9, 13, 17,
       14, 18, 19])

大きな行列でない限り、より単純です。

于 2013-01-10T13:39:10.753 に答える
1

これが本当に欲しいものかどうかはわかりませんが、多分:

>>> import numpy as np
>>> ar = np.random.random((4,4))
>>> ar
array([[ 0.04844116,  0.10543146,  0.30506354,  0.4813217 ],
       [ 0.59962641,  0.44428831,  0.16629692,  0.65330539],
       [ 0.61854927,  0.6385717 ,  0.71615447,  0.13172049],
       [ 0.05001291,  0.41577457,  0.5579213 ,  0.7791656 ]])
>>> ar.diagonal()
array([ 0.04844116,  0.44428831,  0.71615447,  0.7791656 ])
>>> ar[::-1].diagonal()
array([ 0.05001291,  0.6385717 ,  0.16629692,  0.4813217 ])

編集 一般的な解決策として、任意の形状の配列の場合、次を使用できます

import numpy as np
shape = tuple([np.random.randint(3,10) for i in range(2)])
ar = np.arange(np.prod(shape)).reshape(shape)
out = np.hstack([ar[::-1].diagonal(offset=x) \
                for x in np.arange(-ar.shape[0]+1,ar.shape[1]-1)])
print ar
print out

たとえば、与える

[[ 0  1  2  3  4]
 [ 5  6  7  8  9]
 [10 11 12 13 14]
 [15 16 17 18 19]
 [20 21 22 23 24]]
[ 0  5  1 10  6  2 15 11  7  3 20 16 12  8  4 21 17 13  9 22 18 14 23 19]
于 2013-01-10T12:54:42.233 に答える