在不使用Python循环的情况下反转(翻转)非方形数组的对角线中的值的顺序

问题描述 投票:0回答:2

我追求的是Python代码能够使用numpy反转每个数组反对角线中的值的顺序。

我已经尝试过

np.rot90
np.fliplr
np.transpose
np.flipud
的各种组合,但没有一个能够给我 5x3 数组的原始形状,其中所有对角线都反转了。

知道如何实现这一点吗?

示例:

[[ 1  2  4]
 [ 3  5  7]
 [ 6  8 10]
 [ 9 11 13]
 [12 14 15]]

应该变成:

[[ 1  3  6]
 [ 2  5  9]
 [ 4  8 12]
 [ 7 11 14]
 [10 13 15]]

我想这一定很简单,但不知何故,我还没有找到如何在具有数百万个值的数组上有效地完成它。


受到已经提供的答案(状态 2024-05-23 11:37 CET)的启发,并重新思考完成所需转换的最有效方法是什么,似乎给出一个带有两个索引的简单函数:

Column-X
,
Row-y
数组中的值并返回访问数组所需的索引,就像在对角线上翻转/反转一样,将提供最快的结果。使用这样的函数,数组的对角线翻转版本将获得正确的值,而无需对数组进行操作,就像下面演示的简单情况一样简单:

>>> srcArr
array([[ 1,  2,  3,  4,  5,  6],
       [ 7,  8,  9, 10, 11, 12],
       [13, 14, 15, 16, 17, 18],
       [19, 20, 21, 22, 23, 24]])
>>> def oneBasedXY(column, row):
...     return ( row - 1, column - 1 )
... 
>>> srcArr[oneBasedXY(3,4)]
21
>>> srcArr[(3,4)]
23

从这个角度来看,问题归结为提供函数代码

flipTheOtherDiagonals()

python numpy diagonal
2个回答
0
投票

我认为没有任何有效的方法可以做到这一点。我的做法与我在这个答案中所说的从对角线创建数组类似,但一路上反转对角线。

import numpy as np
from scipy.sparse import diags

a = np.arange(15).reshape(5,3) + 1
n, m = a.shape
print(a)

offsets = np.arange(n+m-1)[::-1]-(a.shape[0]-1)

aflipped = np.fliplr(a)
diagonals = [np.diagonal(aflipped, offset=i) for i in offsets]

b = np.zeros_like(a)
for diagonal, offset in zip(diagonals, offsets):
    b += diags(diagonal[::-1], offset, shape=a.shape).astype(int)
b = np.fliplr(b)
print(b)

0
投票

只要没有更好的答案演示如何避免使用 Python 循环,下面的方法仅使用 numpy 并支持具有任何类型值(也可以是混合)的数组:

#!/usr/bin/python
import numpy as np
## Decide the shape of the test array :
M =3 ; N=5  # ( M-Rows x N-Columns ) 
## Create a test array :
srcArr = np.arange( 11, 10+N*M+1, 
                    dtype=np.uint8).reshape(M,N) ;      print( srcArr ); print( " ---===--- " )
# ---===---===---===---===---===---===---===---===---===---===---===---===---===---===---===---
## Extend the array to the right with   M-1   columns for later "shear" :
tmpArr=np.zeros((M,M-1), dtype=np.uint8) ;#         print(tmpArr );print( " ---===--- " )
extArr=np.concatenate( ( srcArr, tmpArr ), axis=1 ) ;       print( extArr ); print( " ---===--- " )
## Share the extended array using    np.roll()   :
for index in range( 1, M):
    extArr[index]=np.roll(extArr[index], index)
pass;                                                   print( extArr ); print( " ---===--- " )
## And reverse by up/down flipping the order of the former diagonals being now columns :
flpArr = np.flipud(extArr) ;                                print( flpArr ); print( " ---===--- " )
## Diagonals are reversed and will be "rolled" into their former positions in the array :
for index in range( 0, M +N - 1):
    if True : ## The "tricky" part because handling non-square arrays requires handling
        flpArr[:,index]=np.roll( flpArr[:,index], ## of three algorithmic different phases
                ( index + 1 ) if index < min(N,M) ## < Phase A : left, "growing" part of array
                    else ( -1 * (M + abs(N-M) ) + 2* (index + 1 - min(N,M)) ) ## Phase B :
                        * ( 1 if ( M  - min(N,M) ) and (N+M-1 - 2*N  - 1) ## < same "size":
                            else 0 )  if index < (N+M) - min(N,M) - 1
                                else  -(M+N ) + index  + 1 ) ## < Phase C : right, "shinking"
pass;                                                   print(flpArr) ; print( " ---===--- " )
for index in range( 1, M): ## Rolling the array back to its initial shape : 
    flpArr[index]=np.roll( flpArr[index], -index)
pass;                                                   print( flpArr) ; print( " ---===--- " )
tgtArr = flpArr[ :M, :N] ## < cut the final array out of the extended one
pass;                                                   print(tgtArr) ; print( " ---===--- " )

"""
[[ 1  2   3]
      [ 4   5   6]
          [  7   8    9]
              [  10  11 12]
                       [13 14 15]]

    [[ 1    2    3]
    [  4    5    6]
    [  7    8    9]
    [10 11  12]
    [13 14 15]]

                         [[  1    2    3]
                     [ 4    5    6]
              [ 7    8    9]
       [10 11 12]
 [13 14 15]]
"""

代码输出:

[[11 12 13 14 15]
 [16 17 18 19 20]
 [21 22 23 24 25]]
 ---===--- 
[[11 12 13 14 15  0  0]
 [16 17 18 19 20  0  0]
 [21 22 23 24 25  0  0]]
 ---===--- 
[[11 12 13 14 15  0  0]
 [ 0 16 17 18 19 20  0]
 [ 0  0 21 22 23 24 25]]
 ---===--- 
[[ 0  0 21 22 23 24 25]
 [ 0 16 17 18 19 20  0]
 [11 12 13 14 15  0  0]]
 ---===--- 
[[11 16 21 22 23  0  0]
 [ 0 12 17 18 19 24  0]
 [ 0  0 13 14 15 20 25]]
 ---===--- 
[[11 16 21 22 23  0  0]
 [12 17 18 19 24  0  0]
 [13 14 15 20 25  0  0]]
 ---===--- 
[[11 16 21 22 23]
 [12 17 18 19 24]
 [13 14 15 20 25]]
 ---===--- 

上面的输出演示了使用 numpy

np.roll()
的方法,可以“剪切”数组,以便首先获得可用于翻转的对角线,然后将其展开回原始形状。

© www.soinside.com 2019 - 2024. All rights reserved.