2012-05-08 15 views
24

Sono nuovo nello scripting. Ho una tabella (Table1.txt) e ho bisogno di creare un'altra tabella che abbia le righe di Table1 disposte in colonne e viceversa. Ho trovato soluzioni a questo problema per Perl e SQL ma non per Python.Come eseguire la trasposizione da riga a colonna dei dati nella tabella csv?

ho appena iniziato l'apprendimento Python due giorni fa, quindi questo è quanto ho ottenuto:

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

Questo riproduce solo le colonne come colonne. Quello che mi sarebbe piaciuto fare ora è scrivere l'ultima riga come writer.writecol([values]) ma sembra che non ci sia alcun comando del genere e non ho trovato un altro modo di scrivere righe come colonne.

+0

http://stackoverflow.com/questions/4937491/matrix-transpose-in-python – ThePracticalOne

+0

Non esiste una cosa come "scrivere colonne". Puoi solo scrivere righe. La cosa più semplice da fare è leggere * tutti * i dati dal file di input, trasporre le righe e le colonne, quindi scrivere * tutti * i dati trasposti nel file di output. la risposta di spinning_plate è concettualmente più facile da seguire per qualcuno di nuovo in Python, anche se non è così efficiente come potrebbe essere. La risposta di Ashwini è molto più concisa e molto più veloce, ma richiede un po 'più di conoscenza specifica di Python. –

risposta

27

La soluzione in generale trasposizione di una sequenza di iterables è: zip (* original_list)

ingresso

campione:

012.351.641,061 mila
1 2 3 4 5 
6 7 8 9 10 
11 12 13 14 15 

programma:

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

uscita:

1 6 11 

2 7 12 

3 8 13 

4 9 14 

5 10 15 
+4

+1 La soluzione in generale è: 'zip (* original_list)' – Tadeck

+0

Grazie, Ashwini! Questo business zip sembra essere il modo migliore per qualcuno come me che avrà bisogno di fare queste trasposizioni tutto il tempo ora ... Molto apprezzato! – Frank

+0

L'ho appena fatto con la mia lista e ha funzionato. A proposito, perché non devi usare csv.reader per leggere nel file txt? Ho pensato che fosse un prerequisito necessario per il computer per leggere i dati ... – Frank

1

Ecco un modo per farlo, si supponga per semplicità che si desidera solo per stampare gli oggetti in ordine:

# 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] 

Poiché è necessario un array per passare a writer.writerow, si potrebbe fare questo

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

Il 'writer' nel modulo' csv' non ha un metodo 'write'. Devi scrivere una riga alla volta con 'writerow', o scrivere tutte le righe contemporaneamente con' writerows'. –

+0

@JohnY - grazie, spero che questo chiarisca le cose. Il mio pensiero è usare zip non aiuterà davvero questa persona se è nuova nello scripting. – dfb

+1

Concordo sul fatto che 'zip' non sia esattamente una funzione per principianti, specialmente se combinato con l'asterisco nel commento di Tadeck sull'altra risposta. Se sia utile far comparire 'zip' subito dopo dipende se la persona vuole davvero imparare Python, o semplicemente eseguire il suo compito il più rapidamente possibile. (Molti programmatori fanno tutto il loro "codice" da Google per le ricette e, in alcuni casi, questo approccio funziona per loro.) –

32

@ risposta di Ashwini è perfetto. La magia avviene in

zip(*lis) 

Mi spiego perché questo funziona: zip richiederà (nel caso più semplice), due liste e "zip" li: zip([1,2,3], [4,5,6]) diventerà [(1,4), (2,5), (3,6)]. Quindi se consideri la lista esterna come una matrice e le tuple interne come le righe, questa è una trasposizione (cioè, abbiamo trasformato le righe in colonne).

Ora, zip è una funzione di arità arbitraria, quindi si può prendere più di due argomenti:

# 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 

Il problema che stiamo affrontando è che nel tuo caso, non sappiamo quanti argomenti vogliamo passare a zip. Ma almeno, conosciamo già gli argomenti: sono gli elementi di lis! lis è un elenco e ogni elemento di tale elenco è anche un elenco (corrispondente a una riga di numeri nel file di input). Il * è solo un modo per Python di dire una funzione "per favore usa gli elementi di ciò che segue come argomenti e non la cosa stessa!"

Così

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

è esattamente lo stesso di

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

Congrats, ora sei un Python professionista! ;-)

22

Dal momento che stiamo parlando di colonne, righe e trasposizione, forse vale la pena menzionare 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]]) 
1

Giusto per costruire il @Akavall risposta, se si desidera leggere da un file, recepire e quindi salvare di nuovo basta fare:

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

data.T nella linea 3 è dove i dati vengono recepite.

Problemi correlati