web-dev-qa-db-fra.com

Matrix Transpose in Python

J'essaie de créer une fonction de transposition de matrice pour python mais je n'arrive pas à le faire fonctionner. Dites que j'ai

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

et je veux que ma fonction arrive avec

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

Donc, en d'autres termes, si je devais imprimer ce tableau 2D sous forme de colonnes et de lignes, j'aimerais que les lignes se transforment en colonnes et que les colonnes en lignes.

Je l'ai fait jusqu'ici mais ça ne marche pas

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

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')]
291
jfs
>>> 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']]

le générateur de liste crée un nouveau tableau 2D avec des éléments de liste au lieu de tuples.

62
sqwerl

Si vos lignes ne sont pas égales, vous pouvez également utiliser map:

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

Edit: In Python 3 la fonctionnalité de map a été modifiée, itertools.Zip_longest peut être utilisé à la place:
Source: Quoi de neuf dans Python 3.

>>> 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')]
34
bigjim

Beaucoup plus facile avec 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')
15
Irshad Bhat

Pour compléter la réponse de J.F. Sebastian, si vous avez une liste de listes de longueurs différentes, jetez un œil à cet article génial d'ActiveState . En bref:

La fonction intégrée Zip effectue un travail similaire, mais tronque le résultat à la longueur de la liste la plus courte, de sorte que certains éléments des données d'origine risquent d'être perdus par la suite.

Pour gérer une liste de listes de différentes longueurs, utilisez:

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

Le problème avec votre code original était que vous avez initialisé transpose[t] à chaque élément, plutôt qu’une fois par ligne:

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

Cela fonctionne, bien qu'il existe d'autres moyens Pythonic pour accomplir les mêmes choses, y compris l'application Zip de @J.F.

4
Ned Batchelder

La "meilleure" réponse a déjà été soumise, mais je pensais ajouter que vous pouvez utiliser des compréhensions de liste imbriquées, comme indiqué dans le tutoriel Python .

Voici comment vous pouvez obtenir un tableau transposé:

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

Celui-ci préservera la forme rectangulaire, afin que les transpositions suivantes obtiennent le bon résultat:

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

Si vous souhaitez transposer une matrice comme A = np.array ([[1,2], [3,4]]), vous pouvez simplement utiliser AT, mais pour un vecteur comme a = [1,2], aT ne retourne pas une transposition! et vous devez utiliser a.reshape (-1, 1), comme ci-dessous

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
Hassan Bahaloo