Skip to main content
 首页 » 编程设计

python之迭代二维数组的 'orthogonal' 对角线的更多 numpy 方法

2025年05月04日14zengkefu

我有以下代码,它沿着与通常由 np.diagonal 返回的对角线正交的对角线进行迭代。 .它从位置 (0, 0) 开始并朝着右下坐标移动。

代码按预期工作,但它的所有循环都不是很 NumPy ,而且效率低下必须创建许多数组来完成这个技巧。

所以我想知道是否有更好的方法来做到这一点,因为我不知道如何跨越我的数组或使用 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但按照上面代码调用的顺序执行(显示在最后的 print 中)。

迭代沿对角线的哪个方向并不重要(如果 1 和 2 交换位置,以及 3 和 5 等在 A 中)仅对角线与 A 的主对角线正交(产生的主对角线)通过 np.diag(A) )。

这个问题的应用/原因在我之前的问题中(在该问题底部的解决方案部分):Constructing a 2D grid from potentially incomplete list of candidates

请您参考如下方法:

这是一种避免 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 是金色的。它基本上是迭代任何形状为 (4,5) 的二维数组所需的一切,因为二维数组只是 reshape 的一维数组。

如果您的最终目标是生成数组 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.]]