Python:如何转置矩阵的一部分
如果我有这样一个矩阵:Python:如何转置矩阵的一部分,python,python-2.7,matrix,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]] [[1, 2, 3, 4],
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]]
[[1, 2, 3, 4],
[5, 6, 10, 14],
[9, 10, 11, 15],
[13, 14, 15, 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]
我明白了:
matrix = [[1, 2, 3, 4],
[5, 6, 10, 14],
[9, 7, 11, 15],
[13, 8, 12, 16]]
[[1, 2, 3, 4],
[5, 6, 10, 14],
[9, 10, 11, 15],
[13, 14, 15, 16]]
我想把它转置到主对角线和次对角线上
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。此代码仅适用于平方矩阵
由于您在发布的循环中硬编码了长度,因此我假设大小始终为4x4。此代码仅适用于平方矩阵 学习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]])
学习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]])
如果有疑问,请编写一个函数 有没有想过为什么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:]
希望这幅图有助于理解为什么上面代码中的索引是这样的。蓝色部分是覆盖层,较长的彩色部分是底部;将覆盖的零件将灰显
红色部分不会出现在您的问题中,但添加它是为了使代码成为更通用的解决方案;这是base[(len(overlay))+offset::
零件
我希望你知道如何工作
现在我们可以将整个矩阵粘贴到另一个更大的矩阵上,方法是将更改的行粘贴到该矩阵上,并将子矩阵行粘贴到任何更改的行上。请注意,下面的代码几乎是前一句话的直译
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
)如果有疑问,写一个函数
有没有想过为什么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:]
希望这幅图有助于理解为什么上面代码中的索引是这样的。蓝色部分是覆盖层,较长的彩色部分是底部;将覆盖的零件将灰显
红色部分不会出现在您的问题中,但添加它是为了使代码成为更通用的解决方案;这是base[(len(overlay))+offset::
零件
我希望你知道如何工作
现在我们可以将整个矩阵粘贴到另一个更大的矩阵上,方法是将更改的行粘贴到该矩阵上,并将子矩阵行粘贴到任何更改的行上。请注意,下面的代码几乎是前一句话的直译
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
。这不是解决这个问题最常用的方法,但是我想说明为什么问题中的尝试不起作用,以及如何像你最初尝试的那样进行适当的转换
这有几个问题:
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]
首先将矩阵[i][j]
赋给矩阵[j][i]
,然后将矩阵[j][i]
赋回矩阵[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
时交换(或另一种方法):
范围(1,4)内的i的:
对于范围(1,4)内的j:
如果i
这也应该给你你想要的答案(如果交换索引是可以接受的)。这不是解决这个问题的最惯用的方法,但我想说明为什么问题中的尝试不起作用,以及如何像你最初尝试的那样在适当的位置进行转换 这有几个问题:
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]
首先将矩阵[i][j]
赋给矩阵[j][i]
,然后将矩阵[j][i]
赋回矩阵[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]
但这也不起作用。它不起作用,因为每个单元格要交换两次(f除外)