เมทริกซ์ขนย้ายใน Python


143

ฉันกำลังพยายามสร้างฟังก์ชั่นทรานสดิวเซอร์เมทริกซ์สำหรับไพ ธ อน แต่ฉันไม่สามารถใช้งานได้ บอกว่าฉันมี

theArray = [['a','b','c'],['d','e','f'],['g','h','i']]

และฉันต้องการฟังก์ชั่นของฉันมาด้วย

newArray = [['a','d','g'],['b','e','h'],['c', 'f', 'i']]

ดังนั้นกล่าวอีกนัยหนึ่งถ้าฉันจะพิมพ์อาร์เรย์ 2D นี้เป็นคอลัมน์และแถวฉันต้องการให้แถวเปลี่ยนเป็นคอลัมน์และคอลัมน์เป็นแถว

ฉันทำมาจนถึงตอนนี้ แต่มันใช้งานไม่ได้

def matrixTranspose(anArray):
    transposed = [None]*len(anArray[0])
    for t in range(len(anArray)):
        for tt in range(len(anArray[t])):
            transposed[t] = [None]*len(anArray)
            transposed[t][tt] = anArray[tt][t]
    print transposed

คำตอบ:


308

Python 2:

>>> theArray = [['a','b','c'],['d','e','f'],['g','h','i']]
>>> zip(*theArray)
[('a', 'd', 'g'), ('b', 'e', 'h'), ('c', 'f', 'i')]

Python 3:

>>> [*zip(*theArray)]
[('a', 'd', 'g'), ('b', 'e', 'h'), ('c', 'f', 'i')]

15
หากคุณจะวนซ้ำผลที่ได้izipจากitertoolsสามารถบันทึกหน่วยความจำสำหรับอาร์เรย์ขนาดใหญ่
Antony Hatchkins

คุณจะให้มันคืนรายการสำหรับรายการย่อยได้อย่างไร? ชอบ[['a', 'b', 'g'], ['d', 'e', 'h'], ['c', 'f', 'i']]แทน[('a', 'd', 'g'), ('b', 'e', 'h'), ('c', 'f', 'i')]?
acollection_

13
map(list, zip(*theArray))@acollection_:
jfs

1
@AntonyHatchkins ไม่จำเป็นต้องใช้กับ Python 3.0 ขึ้นไป ที่นั่นzipส่งคืนตัววนซ้ำแล้ว: docs.python.org/3.0/whatsnew/…
xuiqzy

1
@xuiqzy ไม่ใช่ว่าฉันไม่ทราบ แต่มันเป็นเรื่องจริง
Antony Hatchkins

64
>>> theArray = [['a','b','c'],['d','e','f'],['g','h','i']]
>>> [list(i) for i in zip(*theArray)]
[['a', 'd', 'g'], ['b', 'e', 'h'], ['c', 'f', 'i']]

ตัวสร้างรายการสร้างอาร์เรย์ 2d ใหม่พร้อมไอเท็มรายการแทนที่จะเป็นสิ่งอันดับ


นี่คือวิธีที่จะไปหากคุณต้องการกำหนดผลลัพธ์ให้กับตัวแปร (ตรงข้ามกับ, เช่นวนซ้ำโดยตรง) - สมมติว่าคุณต้องการรายการแทนที่จะเป็นสิ่งอันดับตามที่กล่าวไว้
ASL

ตัวเลือกอื่น (โดยนัยโดยความเห็นในคำตอบที่ยอมรับ) จะเป็น:list(map(list, zip(*theArray)))
ASL

37

หากแถวของคุณไม่เท่ากันคุณสามารถใช้map:

>>> uneven = [['a','b','c'],['d','e'],['g','h','i']]
>>> map(None,*uneven)
[('a', 'd', 'g'), ('b', 'e', 'h'), ('c', None, 'i')]

แก้ไข: ใน Python 3 การทำงานของการmapเปลี่ยนแปลงitertools.zip_longestสามารถใช้แทน:
ที่มา: มีอะไรใหม่ใน Python 3.0

>>> import itertools
>>> uneven = [['a','b','c'],['d','e'],['g','h','i']]
>>> list(itertools.zip_longest(*uneven))
[('a', 'd', 'g'), ('b', 'e', 'h'), ('c', None, 'i')]

15

ง่ายขึ้นด้วย numpy:

>>> arr = np.array([[1,2,3],[4,5,6],[7,8,9]])
>>> arr
array([[1, 2, 3],
       [4, 5, 6],
       [7, 8, 9]])
>>> arr.T
array([[1, 4, 7],
       [2, 5, 8],
       [3, 6, 9]])
>>> theArray = np.array([['a','b','c'],['d','e','f'],['g','h','i']])
>>> theArray 
array([['a', 'b', 'c'],
       ['d', 'e', 'f'],
       ['g', 'h', 'i']], 
      dtype='|S1')
>>> theArray.T
array([['a', 'd', 'g'],
       ['b', 'e', 'h'],
       ['c', 'f', 'i']], 
      dtype='|S1')

6

ปัญหาเกี่ยวกับรหัสต้นฉบับของคุณคือคุณเริ่มต้นtranspose[t]ทุกองค์ประกอบแทนที่จะเป็นเพียงหนึ่งครั้งต่อแถว:

def matrixTranspose(anArray):
    transposed = [None]*len(anArray[0])
    for t in range(len(anArray)):
        transposed[t] = [None]*len(anArray)
        for tt in range(len(anArray[t])):
            transposed[t][tt] = anArray[tt][t]
    print transposed

วิธีนี้ใช้ได้ผลแม้ว่าจะมีวิธี Pythonic มากกว่าที่จะทำสิ่งเดียวกันให้สำเร็จรวมถึงzipแอปพลิเคชันของ @ JF


1
โปรดทราบว่าการใช้งานนี้ไม่ทำงานกับเมทริกซ์ที่มีจำนวนคอลัมน์และแถวต่างกัน
Vector

4

ให้เสร็จสมบูรณ์คำตอบ JF เซบาสเตียนถ้าคุณมีรายชื่อของรายการที่มีความยาวแตกต่างกันตรวจสอบการโพสต์ที่ยิ่งใหญ่นี้จาก ActiveState ในระยะสั้น:

ฟังก์ชันซิปในตัวทำหน้าที่คล้ายกัน แต่ตัดผลลัพธ์เป็นความยาวของรายการที่สั้นที่สุดดังนั้นองค์ประกอบบางอย่างจากข้อมูลดั้งเดิมอาจหายไปในภายหลัง

ในการจัดการรายการที่มีความยาวต่างกันให้ใช้:

def transposed(lists):
   if not lists: return []
   return map(lambda *row: list(row), *lists)

def transposed2(lists, defval=0):
   if not lists: return []
   return map(lambda *row: [elem or defval for elem in row], *lists)

นั่นเป็นเรื่องที่ดี อย่างไรก็ตามเมทริกซ์ไม่มีรายการที่มีความยาวต่างกัน
Olli

ขึ้นอยู่กับวิธีเก็บรักษา
Franck Dernoncourt

3

คำตอบที่ "ดีที่สุด" ได้ถูกส่งมา แต่ฉันคิดว่าฉันจะเพิ่มที่คุณสามารถใช้ comprehensions รายการซ้อนกันเท่าที่เห็นในหลามกวดวิชา

นี่คือวิธีที่คุณจะได้รับอาร์เรย์ transposed:

def matrixTranspose( matrix ):
    if not matrix: return []
    return [ [ row[ i ] for row in matrix ] for i in range( len( matrix[ 0 ] ) ) ]

1

อันนี้จะรักษารูปทรงสี่เหลี่ยมเพื่อให้การสลับที่ตามมาจะได้รับผลลัพธ์ที่ถูกต้อง:

import itertools
def transpose(list_of_lists):
  return list(itertools.izip_longest(*list_of_lists,fillvalue=' '))

1

คุณสามารถลองทำสิ่งนี้ด้วยรายการความเข้าใจดังต่อไปนี้

matrix = [['a','b','c'],['d','e','f'],['g','h','i']] n = len(matrix) transpose = [[row[i] for row in matrix] for i in range(n)] print (transpose)


0

ถ้าคุณต้องการแปลงเมทริกซ์เช่น A = np.array ([[1,2], [3,4]]) คุณก็สามารถใช้ AT ได้ แต่สำหรับเวกเตอร์เช่น = [1,2], aT ไม่คืนขนย้าย! และคุณต้องใช้ a.reshape (-1, 1) ดังต่อไปนี้

import numpy as np
a = np.array([1,2])
print('a.T not transposing Python!\n','a = ',a,'\n','a.T = ', a.T)
print('Transpose of vector a is: \n',a.reshape(-1, 1))

A = np.array([[1,2],[3,4]])
print('Transpose of matrix A is: \n',A.T)

0

คุณสามารถทำได้โดยใช้ความเข้าใจของหลาม

arr = [
    ['a', 'b', 'c'], 
    ['d', 'e', 'f'], 
    ['g', 'h', 'i']
]
transpose = [[arr[y][x] for y in range(len(arr))] for x in range(len(arr[0]))]

แม้ว่านี่อาจเป็นคำตอบที่ถูกต้อง โค้ดสองบรรทัดไม่มีประโยชน์อย่างมากหากไม่มีคำอธิบายว่าอะไรและจะแก้ไขคำถามเดิมได้อย่างไร กรุณาให้รายละเอียดคำตอบของคุณ
RyanNerd

1
เมื่อโพสต์คำตอบใหม่สำหรับคำถามเก่าความคาดหวังนั้นสูง โปรดอย่าโพสต์วิธีการแก้ปัญหาที่ด้อยกว่าให้กับคนที่โพสต์แล้ว
Jean-François Fabre

-1
def matrixTranspose(anArray):
  transposed = [None]*len(anArray[0])

  for i in range(len(transposed)):
    transposed[i] = [None]*len(transposed)

  for t in range(len(anArray)):
    for tt in range(len(anArray[t])):            
        transposed[t][tt] = anArray[tt][t]
  return transposed

theArray = [['a','b','c'],['d','e','f'],['g','h','i']]

print matrixTranspose(theArray)

-3
#generate matrix
matrix=[]
m=input('enter number of rows, m = ')
n=input('enter number of columns, n = ')
for i in range(m):
    matrix.append([])
    for j in range(n):
        elem=input('enter element: ')
        matrix[i].append(elem)

#print matrix
for i in range(m):
    for j in range(n):
        print matrix[i][j],
    print '\n'

#generate transpose
transpose=[]
for j in range(n):
    transpose.append([])
    for i in range (m):
        ent=matrix[i][j]
        transpose[j].append(ent)

#print transpose
for i in range (n):
    for j in range (m):
        print transpose[i][j],
    print '\n'

-4
a=[]
def showmatrix (a,m,n):
    for i in range (m):
        for j in range (n):
            k=int(input("enter the number")
            a.append(k)      
print (a[i][j]),

print('\t')


def showtranspose(a,m,n):
    for j in range(n):
        for i in range(m):
            print(a[i][j]),
        print('\t')

a=((89,45,50),(130,120,40),(69,79,57),(78,4,8))
print("given matrix of order 4x3 is :")
showmatrix(a,4,3)


print("Transpose matrix is:")
showtranspose(a,4,3)


-4
def transpose(matrix):
    listOfLists = []
    for row in range(len(matrix[0])):
        colList = []
        for col in range(len(matrix)):
            colList.append(matrix[col][row])
    listOfLists.append(colList)

    return listOfLists

มันใช้งานง่ายสำหรับการขนย้ายแม้ว่าจะมีห้องสมุดอย่างที่กล่าวไว้ในคำตอบอื่น ๆ นอกจากนี้ยังมี
Ravneet Singh


-4

Python โปรแกรมเพื่อแปลงเมทริกซ์:

row,col = map(int,input().split())
matrix = list()

for i in range(row):
    r = list(map(int,input().split()))
    matrix.append(r)

trans = [[0 for y in range(row)]for x in range(col)]

for i in range(len(matrix[0])):
    for j in range(len(matrix)):
        trans[i][j] = matrix[j][i]     

for i in range(len(trans)):
    for j in range(len(trans[0])):
        print(trans[i][j],end=' ')
    print(' ')

1
มันไม่มีประโยชน์เลย!
tripulse
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.