2012-05-08 25 views
24

Soy nuevo en scripting. Tengo una tabla (Table1.txt) y necesito crear otra tabla que tenga las filas de Table1 dispuestas en columnas y viceversa. He encontrado soluciones a este problema para Perl y SQL, pero no para Python.¿Cómo hacer la transposición de datos de fila a columna en la tabla csv?

simplemente empecé a aprender Python hace dos días, así que esto es por lo que yo tengo:

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

Esto sólo reproduce las columnas como columnas. Lo que me hubiera gustado hacer ahora es escribir la última línea como writer.writecol([values]), pero parece que no hay un comando como ese y no he encontrado otra manera de escribir filas como columnas.

+0

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

+0

No existe la "escritura de columnas". Solo puedes escribir filas. Lo más simple es leer * todos * los datos del archivo de entrada, transponer las filas y columnas y luego escribir * todos * los datos transpuestos en el archivo de salida. La respuesta de spinning_plate es conceptualmente más fácil de seguir para alguien nuevo en Python, aunque no tan eficiente como podría ser. La respuesta de Ashwini es mucho más concisa y mucho más rápida, pero requiere un poco más de conocimiento específico de Python. –

Respuesta

27

La solución, en general, para transponer una secuencia de iterables es: zip (* original_list)

entrada

muestra:

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

programa:

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

de salida:

1 6 11 

2 7 12 

3 8 13 

4 9 14 

5 10 15 
+4

+1 La solución en general es: 'zip (* original_list)' – Tadeck

+0

¡Gracias, Ashwini! Este negocio zip parece ser el mejor camino para alguien como yo, que tendrá que hacer estas transposiciones todo el tiempo ... ¡Muy apreciado! – Frank

+0

Lo acabo de hacer con mi lista y funcionó. Por cierto, ¿por qué no tienes que usar el lector csv para leer en el archivo txt? Pensé que era un requisito previo necesario para que la computadora lea los datos ... – Frank

1

Aquí hay una manera de hacerlo, asume por simplicidad que lo que desea imprimir los objetos en orden:

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

Ya que se necesita una matriz para pasar a writer.writerow, usted podría hacer esto

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

El 'escritor' en el módulo' csv' no tiene un método 'write'. Tienes que escribir una fila a la vez con 'writerow', o escribir todas las filas a la vez con' writerows'. –

+0

@JohnY - gracias, espero que esto aclare las cosas. Mi idea es que el uso de zip no ayude realmente a esta persona si es nuevo en las secuencias de comandos. – dfb

+1

Acepto que 'zip' no es exactamente una función para principiantes, especialmente cuando se combina con el asterisco en el comentario de Tadeck sobre la otra respuesta. Si es útil sacar 'zip' inmediatamente depende de si la persona realmente quiere aprender Python, o simplemente hacer su tarea lo más rápido posible. (Muchos de los no programadores hacen toda su "codificación" buscando en Google recetas, y en algunos casos, este enfoque funciona para ellos.) –

32

@ respuesta de Ashwini es perfecto. La magia sucede en

zip(*lis) 

Voy a explicar por qué esto funciona: zip toma (en el caso más simple) y dos listas "cremallera" ellas: zip([1,2,3], [4,5,6]) se convertirá en [(1,4), (2,5), (3,6)]. Entonces, si considera que la lista externa es una matriz y las tuplas internas son las filas, eso es una transposición (es decir, convertimos las filas en columnas).

Ahora, zip es una función de aridad arbitraria, por lo que puede tomar más de dos argumentos:

# 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 

El problema al que nos enfrentamos es que, en su caso, no sabemos cuántos argumentos queremos pasar al zip. Pero al menos, ya conocemos los argumentos: ¡son los elementos de lis! lis es una lista, y cada elemento de esa lista es también una lista (correspondiente a una línea de números en su archivo de entrada). El * es solo una forma de pitones de decir una función "¡utilice los elementos de lo que sigue como argumentos y no la cosa en sí!"

Así

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

es exactamente el mismo que

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

Felicidades, ahora eres un pitón profesional! ;-)

22

Ya que estamos hablando acerca de las columnas, filas y transposiciones, tal vez vale la pena mencionar 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

Sólo para construir el @Akavall respuesta, si desea leer desde un archivo, transponer y luego guardar de nuevo sólo hacer:

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

data.T en la tercera línea es donde los datos se transpone.

Cuestiones relacionadas