Pomiń nagłówki podczas edycji pliku csv przy użyciu Pythona

209

Korzystam z kodu, o którym mowa poniżej, do edycji pliku CSV za pomocą języka Python. Funkcje wywoływane w kodzie tworzą górną część kodu.

Problem: Chcę, aby poniższy kod zaczął edytować plik CSV z 2. rzędu. Chcę, aby wykluczył 1. wiersz zawierający nagłówki. Obecnie stosuje funkcje tylko w pierwszym rzędzie, a mój wiersz nagłówka ulega zmianie.

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

Próbowałem rozwiązać ten problem, inicjując rowzmienną, 1ale to nie działało.

Proszę o pomoc w rozwiązaniu tego problemu.

Martijn Pieters
źródło

Odpowiedzi:

370

Twoja readerzmienna jest iterowalna, zapętlając ją, odzyskujesz wiersze.

Aby pominąć jeden element przed pętlą, wystarczy wywołać next(reader, None)i zignorować zwracaną wartość.

Możesz także nieco uprościć kod; użyj otwartych plików jako menedżerów kontekstu, aby automatycznie je zamknąć:

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.

Jeśli chcesz zapisać nagłówek do nieprzetworzonego pliku wyjściowego, to również łatwe, przekaż dane wyjściowe next()do writer.writerow():

headers = next(reader, None)  # returns the headers or `None` if the input is empty
if headers:
    writer.writerow(headers)
Martijn Pieters
źródło
22
Alternatywą jest także użycie for row in islice(reader, 1, None)- choć mniej wyraźne niż w nextprzypadku najprostszych zadań „pomiń jedną linię”, pomijanie wielu wierszy nagłówka (lub uzyskiwanie tylko niektórych fragmentów itp.) - jest to całkiem przydatne
Jon Clements
Rozważałbym użycietry: writer.write(next(reader))... except StopIteration: # handle empty reader
Jon Clements
@JonClements: Być może. Działa to wystarczająco dobrze, bez konieczności uczenia o try:/ except:.
Martijn Pieters
1
@JonClements: Zaletą wyraźnej nextiteracji jest to, że jest „darmowa”; islicezawinąłoby readerwieczność, dodając (co prawda bardzo niewielką ilość) narzut do każdej iteracji. Z consumeprzepisuitertools można szybko ominąć wiele wartości, bez dodawania opakowania do późniejszego użycia, w przypadku, gdy islicemiałoby to wartość „ startale” end, ale „nie” , dzięki czemu narzut nic cię nie zyskuje.
ShadowRanger
120

Innym sposobem rozwiązania tego problemu jest użycie klasy DictReader, która „pomija” wiersz nagłówka i używa go do dozwolonego indeksowania nazwanego.

Biorąc pod uwagę „foo.csv” w następujący sposób:

FirstColumn,SecondColumn
asdf,1234
qwer,5678

Użyj DictReader w następujący sposób:

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
źródło
21
Wydaje mi się, że to jest prawdziwa odpowiedź, ponieważ pytanie wydaje się być przykładem problemu XY .
MariusSiuram
3
DictReader to zdecydowanie najlepsza droga
Javier Arias
4
Należy zauważyć, że działa to tylko wtedy, gdy pominięto parametr nazw pól podczas konstruowania DictReadera. Według dokumentacji: If the fieldnames parameter is omitted, the values in the first row of the file f will be used as the fieldnames.Patrz docs.python.org/2/library/csv.html
BuvinJ
7

Robienie row=1niczego nie zmieni, ponieważ po prostu nadpiszesz je wynikami pętli.

Chcesz zrobić, next(reader)aby pominąć jeden wiersz.

Katriel
źródło
Próbowałem zmienić go na, for row in next(reader):ale powoduje to IndexError: string index out of rangebłąd
Użyj go przed pętlą for: next(reader); for row in reader:....
dlazesz