Python:如何转置部分矩阵

时间:2015-11-30 01:39:38

标签: python python-2.7 matrix

如果我有这样的矩阵:

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]]

我想把它转移到主对角线和辅助对角线上。

4 个答案:

答案 0 :(得分: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]])

答案 1 :(得分: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's list slicing是如何运作的。

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

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。)

答案 2 :(得分:0)

from math import ceil
# get rid of first row and first element in each row
m2 = [x[1:] for x in matrix[1:]]
for i in range(ceil(len(m2)/2)): # just top half of the rows
    for j in range(i, len(m2[i])): # just above the diagonal
        m2[i][j], m2[j][i] = m2[j][i], m2[i][j]
# create list with first element in matrix and rest from m2
m3 = []
for i in range(len(m1)):
    row = [matrix[i][0]]
    row.extend(m2[i]) 
    m3.append(line)
# now all m3 is missing is the first row 
m3.insert(0, matrix[0])

由于你在发布的循环中硬编码了长度,我认为大小总是4x4。此代码仅适用于方形矩阵。

答案 3 :(得分: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],这意味着两者在最后都会有相同的号码。< / p>

如果你这样做,你可以改为交换它们:

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]

这也应该为您提供您正在寻找的答案(如果可以接受原地交换索引)。