Python:如何转置矩阵的一部分

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

如果我有一个这样的矩阵:

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

我怎样才能得到这个:

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

也就是说,如何排除第一行和第一列, 其余的转置吗?

我尝试了这个,它使矩阵保持不变:

for i in range(1, 4):
    for j in range(1, 4):
        temp = copy.deepcopy(matrix[i][j])
        matrix[i][j] = matrix[j][i]
        matrix[j][i] = temp

当我尝试时:

new_matrix = list(matrix)
for i in range(1, 4):
    for j in range(1, 4):
        matrix[i][j] = new_matrix[j][i]
        matrix[j][i] = new_matrix[i][j]

我明白了:

[[1, 2, 3, 4], 
[5, 6, 10, 14], 
[9, 10, 11, 15], 
[13, 14, 15, 16]]

我想将它转置到主对角线和次对角线上。

python python-2.7 matrix
5个回答
3
投票

学习 numpy,即使对于这个简单的任务也是值得的。

import numpy as np

m=np.array(range(1,17)).reshape(4,4)    
m[1:,1:]=m[1:,1:].transpose()                                                                                     

array([[ 1,  2,  3,  4],
       [ 5,  6, 10, 14],
       [ 9,  7, 11, 15],
       [13,  8, 12, 16]])

2
投票

如有疑问,请编写一个函数。

有没有想过为什么 Python 缺少用于转置矩阵的内置函数?这是因为

zip
已经做到了。但是
zip
返回一个元组序列,并且您需要列表,所以让我们把它包装起来。

def transpose(matrix):
    return [list(row) for row in zip(*matrix)]

我们需要转置一个子矩阵。我们如何提取它?

def submatrix(matrix, skip=1):
    return [row[skip:] for row in matrix[skip:]]

事实证明,我们需要一个函数来将一个列表的内容粘贴到另一个更大列表的内容上。为了简单起见,下面的函数假设较小的覆盖列表永远不会超过较大的基本列表的边界。

def pasteOver(base, overlay, offset):
    """Paste overlay list over base list, starting at offset.

    Works even when overlay is not touching either end of base."""
    return base[:offset] + overlay + base[(len(overlay)) + offset:]

这张图希望有助于理解为什么上面代码中的索引是这样的。蓝色部分是

overlay
,较长的彩色部分是
base
;将要覆盖的部分呈灰色。

pic

红色部分不会出现在你的问题中,但添加它是为了使代码成为更通用的解决方案;这是

base[(len(overlay)) + offset:]
部分。

我希望你知道 Python 的列表切片是如何工作的。

现在我们可以将整个矩阵粘贴到另一个更大的矩阵上,方法是将更改的行粘贴到其上,并将子矩阵行粘贴到任何更改的行上。请注意下面的代码几乎是前一句的直译。

def graft(matrix, submatrix, offset):
    """Overlays submatrix on matrix at given offset from top/left."""
    changing_rows = matrix[offset : offset + len(submatrix)]
    changed_rows = [pasteOver(row, sub_row, offset)
                    for (row, sub_row) in zip(changing_rows, submatrix)]
    return pasteOver(matrix, changed_rows, offset)

现在可以轻松组合内容来粘贴转置子矩阵:

def subTranspose(matrix, skip=1):
    sub_transposed = transpose(submatrix(matrix, skip))
    return graft(matrix, sub_transposed, skip)

请注意,每个函数都几乎短得滑稽且简单,因此“它的正确性非常明显”(q)。另请注意每个函数都是“纯粹的”,它永远不会更改传递给它的数据或有任何其他副作用。如果该代码位于真实的代码库中,将更易于阅读、测试、重用和维护。 (但是如果你的矩阵真的很大,无论如何都要使用

numpy

。)

    


0
投票
由于您在发布的循环中硬编码了长度,因此我假设大小始终为 4x4。此代码仅适用于方阵。 


0
投票

这有几个问题:

new_matrix = list(matrix) for i in range(1, 4): for j in range(1, 4): matrix[i][j] = new_matrix[j][i] matrix[j][i] = new_matrix[i][j]

首先将 
matrix[i][j]

分配给

matrix[j][i]
,然后将
matrix[j][i]
分配回
matrix[i][j]
,这意味着两者最后都会有相同的数字。

如果你这样做,你会交换它们:

for i in range(1, 4): for j in range(1, 4): matrix[i][j], matrix[j][i] = matrix[j][i], matrix[i][j]

但这也行不通。  它不起作用,因为我们将每个单元格交换两次(无论如何对角线都不重要)。

我们可以通过只去对角线来确保只交换一次。 一种方法是仅在

i

小于

j
时进行交换(或反之亦然):

for i in range(1, 4): for j in range(1, 4): if i < j: matrix[i][j], matrix[j][i] = matrix[j][i], matrix[i][j]

这也应该给你你正在寻找的答案(如果就地交换索引是可以接受的)。


0
投票

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