Estoy tratando de construir una función que elimine y ordene dinámicamente filas en función de los números de columna en los que se pasa. Hasta ahora he definido lo siguiente:

import csv

def delete(rows_to_keep):
    with open('file.csv','r') as source:
        rdr= csv.reader( source )
        with open('reordered.csv','w') as result:
            wtr= csv.writer( result, delimiter=',', lineterminator='\n' )
            for r in rdr:
                wtr.writerow( ... )

rows_to_keep = [1, 3, 5, 6]

delete(rows_to_keep)

Sin embargo, en lo anterior, me gustaría que el ... en el escritorow (...) sea reemplazado por argumentos de la siguiente manera:

... = r[1], r[3], r[5], r[6]

I.e.

wtr.writerow( r[1], r[3], r[5], r[6] )

Y tenga el número de argumentos y el cambio de orden dependiendo de lo que se pasa.

No estoy muy seguro de cómo podría hacer esto si de repente la matriz tiene 10 valores. ¿¿Algunas ideas??

0
NickP 13 may. 2016 a las 15:00

3 respuestas

La mejor respuesta

Use rows_to_keep en un bucle para construir una lista con la nueva secuencia de valores que desea escribir. Luego pase esa lista a writerow(); no acepta un número arbitrario de argumentos, por lo que debe llamarlo con una lista de una forma u otra. Algo como esto:

rows_to_keep = [1, 3, 5, 6]
...
for row in rdr:
    newrow = list()
    for n in rows_to_keep:
        newrow.append(row[n])
    wtr.writerow(newrow)

PD. O usa una comprensión si lo prefieres. Mismo resultado (si se usa correctamente).

for row in rdr:
    newrow = [row[n] for n in rows_to_keep]
    wrt.writerow(newrow)
2
alexis 13 may. 2016 a las 12:10

Puedes usar una lista de comprensión:

wtr.writerow([r[col] for col in rows_to_keep])
2
Daniel Roseman 13 may. 2016 a las 12:13

Quizás quisiste decir columns_to_keep y pasar la lista de columnas para mantenerla como una lista para la función. Puedes usar operator.itemgetter aquí

import csv
import operator

def prune_columns(columns_to_keep):
    with open('file.csv', 'r') as source,\
         open('reordered.csv','w') as result:
        rdr = csv.reader( source )
        wtr = csv.writer(result, delimiter=',', lineterminator='\n' )

        select = operator.itemgetter(*columns_to_keep)
        # select is now a function that returns a tuple that 
        # returns elements 1, 3, 5 and 6 of the input

        for row in rdr:
            wtr.writerow(select(row))

prune_columns(columns_to_keep=[1, 3, 5, 6])
1
Antti Haapala 13 may. 2016 a las 12:15