Salta le intestazioni quando modifichi un file CSV usando Python


209

Sto usando il codice di seguito indicato per modificare un CSV utilizzando Python. Le funzioni chiamate nel codice formano la parte superiore del codice.

Problema: voglio che il codice indicato di seguito inizi a modificare il CSV dalla seconda riga, voglio escludere la prima riga che contiene le intestazioni. In questo momento sta applicando le funzioni solo sulla 1a riga e la mia riga di intestazione sta 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()

Ho provato a risolvere questo problema inizializzando la rowvariabile 1ma non ha funzionato.

Aiutatemi a risolvere questo problema.


Risposte:


371

La tua readervariabile è iterabile, scorrendo su di essa recuperi le righe.

Per farlo saltare un elemento prima del ciclo, è sufficiente chiamare next(reader, None)e ignorare il valore restituito.

Puoi anche semplificare un po 'il tuo codice; utilizzare i file aperti come gestori di contesto per chiuderli automaticamente:

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.

Se si desidera scrivere l'intestazione nel file di output non elaborato, anche questo è facile, passare l'output di next()a writer.writerow():

headers = next(reader, None)  # returns the headers or `None` if the input is empty
if headers:
    writer.writerow(headers)

22
Un'alternativa è anche l'uso for row in islice(reader, 1, None)- sebbene meno esplicito rispetto nextalla maggior parte dei semplici lavori "salta una riga", per saltare più righe di intestazione (o ottenere solo alcuni blocchi ecc.) È abbastanza utile
Jon Clements

Prenderei in considerazione l'uso ditry: writer.write(next(reader))... except StopIteration: # handle empty reader
Jon Clements

@JonClements: Forse. Funziona abbastanza bene senza dover insegnare try:/ except:.
Martijn Pieters

1
@JonClements: Il vantaggio nextdell'iterazione esplicita è che è "gratuito"; isliceavvolgerebbe l' readeraggiunta per sempre (una quantità molto ridotta di) sovraccarico a ogni iterazione. La consumericetta diitertools può essere utilizzata per saltare molti valori rapidamente, senza aggiungere il wrapping all'utilizzo successivo, nel caso in cui isliceavrebbe un startma no end, quindi l'overhead non ti sta guadagnando nulla.
ShadowRanger,

120

Un altro modo per risolvere questo problema è utilizzare la classe DictReader, che "salta" la riga di intestazione e la utilizza per consentire l'indicizzazione denominata.

Dato "foo.csv" come segue:

FirstColumn,SecondColumn
asdf,1234
qwer,5678

Usa DictReader in questo modo:

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

21
Sento che questa è la vera risposta, poiché la domanda sembra essere un esempio del problema XY .
MariusSiuram,

3
DictReader è sicuramente la strada da percorrere
Javier Arias il

4
È importante notare che questo funziona solo se si omette il parametro dei nomi dei campi durante la costruzione di DictReader. Per la documentazione: If the fieldnames parameter is omitted, the values in the first row of the file f will be used as the fieldnames.vedere docs.python.org/2/library/csv.html
BuvinJ

7

Fare row=1non cambierà nulla, perché lo sovrascriverai solo con i risultati del ciclo.

Vuoi fare next(reader)per saltare una riga.


Ho provato a cambiarlo in for row in next(reader):ma mi sta dando IndexError: string index out of rangeerrore

Usalo prima del ciclo for: next(reader); for row in reader:....
dlazesz
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.