Omita los encabezados al editar un archivo csv con Python

209

Estoy usando el código mencionado a continuación para editar un csv usando Python. Las funciones llamadas en el código forman la parte superior del código.

Problema: quiero que el código mencionado a continuación comience a editar el csv desde la segunda fila, quiero que excluya la primera fila que contiene encabezados. En este momento está aplicando las funciones solo en la primera fila y mi fila de encabezado está cambiando.

in_file = open("tmob_notcleaned.csv", "rb")
reader = csv.reader(in_file)
out_file = open("tmob_cleaned.csv", "wb")
writer = csv.writer(out_file)
row = 1
for row in reader:
    row[13] = handle_color(row[10])[1].replace(" - ","").strip()
    row[10] = handle_color(row[10])[0].replace("-","").replace("(","").replace(")","").strip()
    row[14] = handle_gb(row[10])[1].replace("-","").replace(" ","").replace("GB","").strip()
    row[10] = handle_gb(row[10])[0].strip()
    row[9] = handle_oem(row[10])[1].replace("Blackberry","RIM").replace("TMobile","T-Mobile").strip()
    row[15] = handle_addon(row[10])[1].strip()
    row[10] = handle_addon(row[10])[0].replace(" by","").replace("FREE","").strip()
    writer.writerow(row)
in_file.close()    
out_file.close()

Traté de resolver este problema inicializando la rowvariable 1pero no funcionó.

Por favor, ayúdame a resolver este problema.

Martijn Pieters
fuente

Respuestas:

371

Su readervariable es iterable, al recorrerla recupera las filas.

Para que omita un elemento antes de su ciclo, simplemente llame next(reader, None)e ignore el valor de retorno.

También puedes simplificar un poco tu código; use los archivos abiertos como gestores de contexto para cerrarlos automáticamente:

with open("tmob_notcleaned.csv", "rb") as infile, open("tmob_cleaned.csv", "wb") as outfile:
   reader = csv.reader(infile)
   next(reader, None)  # skip the headers
   writer = csv.writer(outfile)
   for row in reader:
       # process each row
       writer.writerow(row)

# no need to close, the files are closed automatically when you get to this point.

Si desea escribir el encabezado en el archivo de salida sin procesar, también es fácil, pase la salida de next()a writer.writerow():

headers = next(reader, None)  # returns the headers or `None` if the input is empty
if headers:
    writer.writerow(headers)
Martijn Pieters
fuente
22
Una alternativa también es usar for row in islice(reader, 1, None), aunque menos explícito que nextpara la mayoría de los trabajos simples de "omitir una línea", para omitir varias filas de encabezado (u obtener solo ciertos fragmentos, etc.) es bastante útil
Jon Clements
Consideraría usartry: writer.write(next(reader))... except StopIteration: # handle empty reader
Jon Clements
@ JonClements: Quizás. Esto funciona lo suficientemente bien sin tener que enseñar sobre try:/ except:.
Martijn Pieters
1
@ JonClements: La ventaja de la nextiteración explícita es que es "gratis"; isliceenvolvería la readersobrecarga agregando para siempre (una cantidad ciertamente muy pequeña) a cada iteración. La consumereceta deitertools se puede usar para omitir muchos valores rápidamente, sin agregar envoltura al uso posterior, en el caso de isliceque tenga un startpero no end, por lo que la sobrecarga no le está dando nada.
ShadowRanger
120

Otra forma de resolver esto es usar la clase DictReader, que "omite" la fila del encabezado y la usa para permitir la indexación con nombre.

Dado "foo.csv" de la siguiente manera:

FirstColumn,SecondColumn
asdf,1234
qwer,5678

Use DictReader así:

import csv
with open('foo.csv') as f:
    reader = csv.DictReader(f, delimiter=',')
    for row in reader:
        print(row['FirstColumn'])  # Access by column header instead of column number
        print(row['SecondColumn'])
Chad Zawistowski
fuente
21
Siento que esta es la respuesta real, ya que la pregunta parece ser un ejemplo de problema XY .
MariusSiuram
3
DictReader es definitivamente el camino a seguir
Javier Arias el
44
Es importante tener en cuenta que esto solo funciona si omite el parámetro de nombres de campo al construir el DictReader. Según la documentación: If the fieldnames parameter is omitted, the values in the first row of the file f will be used as the fieldnames.ver docs.python.org/2/library/csv.html
BuvinJ
7

Hacer row=1no cambiará nada, porque simplemente lo sobrescribirá con los resultados del bucle.

Desea hacer next(reader)para omitir una fila.

Katriel
fuente
Traté de cambiarlo for row in next(reader):pero me está dando un IndexError: string index out of rangeerror
Úselo antes del ciclo for: next(reader); for row in reader:....
dlazesz