Lewati header saat mengedit file csv menggunakan Python

209

Saya menggunakan kode rujukan di bawah ini untuk mengedit csv menggunakan Python. Fungsi yang dipanggil dalam bentuk kode bagian atas kode.

Masalah: Saya ingin kode yang dirujuk di bawah ini mulai mengedit csv dari baris ke-2, saya ingin mengecualikan baris ke-1 yang berisi header. Saat ini sedang menerapkan fungsi pada baris ke-1 saja dan baris header saya semakin berubah.

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

Saya mencoba untuk memecahkan masalah ini dengan menginisialisasi rowvariabel 1tetapi tidak berhasil.

Tolong bantu saya dalam memecahkan masalah ini.

Martijn Pieters
sumber

Jawaban:

371

readerVariabel Anda adalah iterable, dengan mengulanginya Anda mengambil baris.

Untuk membuatnya melewatkan satu item sebelum loop Anda, cukup panggil next(reader, None)dan abaikan nilai kembali.

Anda juga dapat menyederhanakan kode Anda sedikit; gunakan file yang dibuka sebagai manajer konteks agar ditutup secara otomatis:

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.

Jika Anda ingin menulis header ke file output yang belum diproses, itu mudah juga, meneruskan output next()ke writer.writerow():

headers = next(reader, None)  # returns the headers or `None` if the input is empty
if headers:
    writer.writerow(headers)
Martijn Pieters
sumber
22
Alternatif lain adalah menggunakan for row in islice(reader, 1, None)- walaupun kurang eksplisit daripada nextuntuk pekerjaan "lewati satu baris" yang paling sederhana, untuk melewatkan beberapa baris tajuk (atau hanya mendapatkan potongan tertentu dll ...) itu cukup berguna
Jon Clements
Saya akan mempertimbangkan untuk menggunakantry: writer.write(next(reader))... except StopIteration: # handle empty reader
Jon Clements
@ JonClements: Mungkin. Ini berfungsi cukup baik tanpa harus mengajarkan tentang try:/ except:.
Martijn Pieters
1
@ JonClements: Keuntungan untuk nextiterasi eksplisit adalah "gratis"; isliceakan membungkus readerselamanya menambahkan (jumlah yang diakui sangat kecil) overhead untuk setiap iterasi. The consumeresep dariitertools dapat digunakan untuk melewatkan banyak nilai dengan cepat, tanpa menambahkan pembungkus untuk penggunaan berikutnya, dalam kasus di mana isliceakan memiliki starttapi tidak ada end, sehingga biaya overhead tidak mendapatkan apa-apa.
ShadowRanger
120

Cara lain untuk menyelesaikan ini adalah dengan menggunakan kelas DictReader, yang "melompati" baris header dan menggunakannya untuk diizinkan bernama pengindeksan.

Diberikan "foo.csv" sebagai berikut:

FirstColumn,SecondColumn
asdf,1234
qwer,5678

Gunakan DictReader seperti ini:

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
sumber
21
Saya merasa ini adalah jawaban yang sebenarnya, karena pertanyaan itu tampaknya menjadi contoh masalah XY .
MariusSiuram
3
DictReader jelas merupakan jalan yang harus ditempuh
Javier Arias
4
Penting untuk dicatat bahwa ini hanya berfungsi jika Anda menghilangkan parameter nama bidang saat membuat DictReader. Per dokumentasinya: If the fieldnames parameter is omitted, the values in the first row of the file f will be used as the fieldnames.Lihat docs.python.org/2/library/csv.html
BuvinJ
7

Melakukan row=1tidak akan mengubah apa pun, karena Anda hanya akan menimpanya dengan hasil loop.

Anda ingin melakukannya next(reader)untuk melewati satu baris.

Katriel
sumber
Saya mencoba mengubahnya for row in next(reader):tetapi memberi saya IndexError: string index out of rangekesalahan
Gunakan sebelum loop for: next(reader); for row in reader:....
dlazesz