web-dev-qa-db-fra.com

Comment faire une transposition ligne à colonne de données dans une table csv?

Je suis nouveau dans les scripts. J'ai une table (Table1.txt) Et j'ai besoin de créer une autre table qui a les lignes de Table1 disposées en colonnes et vice versa. J'ai trouvé des solutions à ce problème pour Perl et SQL mais pas pour Python.

Je viens de commencer à apprendre Python il y a deux jours, donc c'est pour autant que je suis arrivé:

import csv
import sys

with open(sys.argv[1], "rt") as inputfile:
   readinput = csv.reader(inputfile, delimiter='\t')
   with open("output.csv", 'wt') as outputfile:
      writer = csv.writer(outputfile, delimiter="\t")
      for row in readinput:
            values = [row[0], row[1], row[2], row[3]]
            writer.writerow([values])

Cela reproduit simplement les colonnes sous forme de colonnes. Ce que j'aurais aimé faire maintenant, c'est écrire la dernière ligne comme writer.writecol([values]) mais il semble qu'il n'y ait pas de commande comme ça et je n'ai pas trouvé d'autre moyen d'écrire des lignes comme des colonnes.

29
Frank

La solution en général pour transposer une séquence d'itérables est: Zip (* original_list)

exemple d'entrée:

1   2   3   4   5
6   7   8   9   10
11  12  13  14  15

programme:

with open('in.txt') as f:
  lis = [x.split() for x in f]

for x in Zip(*lis):
  for y in x:
    print(y+'\t', end='')
  print('\n')

sortie:

1   6   11  

2   7   12  

3   8   13  

4   9   14  

5   10  15
31

@ La réponse d'Ashwini est parfaite. La magie opère dans

Zip(*lis)

Permettez-moi d'expliquer pourquoi cela fonctionne: Zip prend (dans le cas le plus simple) deux listes et les "zippe": Zip([1,2,3], [4,5,6]) deviendra [(1,4), (2,5), (3,6)]. Donc, si vous considérez la liste externe comme une matrice et les tuples internes comme des lignes, c'est une transposition (c'est-à-dire que nous avons transformé les lignes en colonnes).

Maintenant, Zip est une fonction d'arité arbitraire, donc il peut prendre plus de deux arguments:

# Our matrix is:
# 1 2 3
# 4 5 6
# 7 8 9

Zip([1,2,3], [4,5,6], [7,8,9])

>>> [(1, 4, 7), (2, 5, 8), (3, 6, 9)]

# Now it is
# 1 4 7
# 2 5 8
# 3 6 9

Le problème auquel nous sommes confrontés est que dans votre cas, nous ne savons pas combien d'arguments nous voulons transmettre à Zip. Mais au moins, nous connaissons déjà les arguments: ce sont les éléments de lis! lis est une liste, et chaque élément de cette liste est également une liste (correspondant à une ligne de nombres dans votre fichier d'entrée). Le * Est juste une façon Python de dire une fonction "veuillez utiliser les éléments de ce qui suit comme arguments et pas la chose elle-même!"

Alors

lis = [[1,2,3], [4,5,6]]
Zip(*lis)

est exactement le même que

Zip([1,2,3], [4,5,6])

Félicitations, vous êtes maintenant un Python pro! ;-)

35
Manuel Ebert

Puisque nous parlons de colonnes, de lignes et de transpositions, il vaut peut-être la peine de mentionner numpy

>>> import numpy as np
>>> x = np.array([[1,2,3],[4,5,6],[7,8,9],[10,11,12]])
>>> x
array([[ 1,  2,  3],
       [ 4,  5,  6],
       [ 7,  8,  9],
       [10, 11, 12]])
>>> x.T
array([[ 1,  4,  7, 10],
       [ 2,  5,  8, 11],
       [ 3,  6,  9, 12]])
23
Akavall

Juste pour construire sur la réponse @Akavall, si vous voulez lire à partir d'un fichier, transposer puis enregistrer à nouveau, faites simplement:

from numpy import genfromtxt, savetxt
data = genfromtxt('in.txt')
savetxt('out.txt',data.T)

data.T dans la 3ème ligne est l'endroit où les données sont transposées.

1
elyase

Voici une façon de le faire, supposons pour simplifier que vous vouliez simplement imprimer les objets dans l'ordre:

  # lets read all the data into a big 2d array
  buffer = []
  for row in readinput: 
        values = [row[0], row[1], row[2], row[3]]  
        buffer.append(values)       

  # what you have in your code
  for i in range(len(buffer)):
      for j in range(len(buffer[0])):
          print buffer[i][j]

  # this is called a transpose; we have buffer[i][j] to read row then column, 
  #    switch i and j around to do the opposite
  for i in range(len(buffer[0])):
      for j in range(len(buffer)):
          print buffer[j][i]

Puisque vous avez besoin d'un tableau pour passer à writer.writerow, tu pourrais faire ça

  for i in range(len(buffer[0])):
      writer.writerow([buffer[j][i] for j in range(len(buffer))])
1
dfb