Transposição de matriz em Python

143

Estou tentando criar uma função de transposição de matriz para python, mas não consigo fazê-lo funcionar. Diga que eu tenho

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

e eu quero que minha função venha com

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

Portanto, em outras palavras, se eu imprimir essa matriz 2D como colunas e linhas, gostaria que as linhas se transformassem em colunas e colunas em linhas.

Eu fiz isso até agora, mas não funciona

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
Julio Diaz
fonte

Respostas:

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')]
jfs
fonte
15
se você estiver indo para percorrer os resultados, izipdesde itertoolspode salvar a memória para grandes matrizes.
Antony Hatchkins 28/03
Como você gostaria que ele retornasse uma lista para as sub-listas? Como em [['a', 'b', 'g'], ['d', 'e', 'h'], ['c', 'f', 'i']]vez de [('a', 'd', 'g'), ('b', 'e', 'h'), ('c', 'f', 'i')]?
Acollection_
13
@acollection_: map(list, zip(*theArray)).
JFS
1
@AntonyHatchkins Isso não é necessário no Python 3.0 e acima. Lá, zipjá retorna um iterador: docs.python.org/3.0/whatsnew/…
xuiqzy
1
@xuiqzy Não é que eu não esteja ciente disso, mas é verdade.
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']]

o gerador de lista cria uma nova matriz 2D com itens de lista em vez de tuplas.

sqwerl
fonte
Este é o caminho a percorrer se você deseja atribuir o resultado a uma variável (em vez de, por exemplo, iterar diretamente sobre ela) - supondo que você queira listas em vez de tuplas, como mencionado.
ASL
Outra opção (conforme implícita nos comentários na resposta aceita) seria:list(map(list, zip(*theArray)))
ASL
37

Se suas linhas não forem iguais, você também pode usar map:

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

Edit: No Python 3, a funcionalidade mapalterada itertools.zip_longestpode ser usada:
Fonte: Novidades do 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')]
bigjim
fonte
15

Muito mais fácil com 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')
Irshad Bhat
fonte
6

O problema com seu código original era que você inicializou transpose[t]em cada elemento, em vez de apenas uma vez por linha:

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

Isso funciona, embora existam mais maneiras Pythonic de realizar as mesmas coisas, incluindo o zipaplicativo @ JF .

Ned Batchelder
fonte
1
Observe que essa implementação não funciona com matrizes que possuem números diferentes de colunas e linhas
Vector
4

Para concluir a resposta de JF Sebastian, se você tiver uma lista de listas com comprimentos diferentes, confira esta excelente postagem do ActiveState . Em resumo:

A função interna zip executa um trabalho semelhante, mas trunca o resultado para o comprimento da lista mais curta, para que alguns elementos dos dados originais possam ser perdidos posteriormente.

Para lidar com a lista de listas com comprimentos diferentes, use:

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)
Franck Dernoncourt
fonte
Isso é bom. No entanto, as matrizes não têm listas com comprimentos diferentes.
Olli
Depende de como eles são armazenados.
Franck Dernoncourt 9/13
3

A "melhor" resposta já foi enviada, mas pensei em acrescentar que você pode usar a compreensão de listas aninhadas, como visto no Tutorial do Python .

Aqui está como você pode obter uma matriz transposta:

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

Este preservará a forma retangular, para que as transposições subsequentes obtenham o resultado certo:

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

você pode tentar isso com compreensão de lista como o seguinte

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)

sharif_42
fonte
0

Se você deseja transpor uma matriz como A = np.array ([[1,2], [3,4]]), então pode simplesmente usar AT, mas para um vetor como a = [1,2], aT não retorna uma transposição! e você precisa usar a.reshape (-1, 1), como abaixo

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)
Hassan Bahaloo
fonte
0

Você pode fazer isso simplesmente usando a compreensão de python.

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]))]
rasoul poordelan
fonte
Embora isso possa ser uma resposta correta. Duas linhas de código não são muito úteis sem uma explicação sobre o que e como ele resolve a questão original. Forneça detalhes para sua resposta.
RyanNerd 27/09/19
1
ao postar uma nova resposta para uma pergunta antiga, as expectativas são altas. Por favor, não publique uma solução inferior à que já foi postada
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)
Asterisco
fonte
-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'
roo.firebolt
fonte
-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)
chaitanya
fonte
-4
def transpose(matrix):
   x=0
   trans=[]
   b=len(matrix[0])
   while b!=0:
       trans.append([])
       b-=1
   for list in matrix:
       for element in list:
          trans[x].append(element)
          x+=1
       x=0
   return trans
mohammad hassan jafari
fonte
-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
fonte
É uma implementação simples para uma transposição, embora também existam bibliotecas como as mencionadas em outras respostas.
Ravneet Singh
-4

`

def transpose(m):
    return(list(map(list,list(zip(*m)))))

`Esta função retornará a transposição

user2412711
fonte
-4

Programa Python para transpor matriz:

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(' ')
MK Rana
fonte
1
Isso não é útil!
Tripulse # 8/19