Пропускайте заголовки під час редагування файлу csv за допомогою Python


209

Я використовую наведений нижче код для редагування csv за допомогою Python. Функції, що викликаються у кодовій формі верхньої частини коду.

Проблема: Я хочу, щоб наведений нижче код почав редагувати csv з 2-го ряду, я хочу, щоб він виключив 1-й рядок, який містить заголовки. Зараз він застосовує функції лише для 1-го ряду, і мій рядок заголовка змінюється.

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

Я намагався вирішити цю проблему, ініціалізуючи rowзмінну до, 1але вона не спрацювала.

Будь ласка, допоможіть мені у вирішенні цього питання.


Відповіді:


370

Ваша readerзмінна є ітерабельною, перебираючи її, ви отримуєте рядки.

Щоб пропустити один елемент перед циклом, просто зателефонуйте next(reader, None)та проігноруйте повернене значення.

Ви також можете трохи спростити свій код; використовувати відкриті файли як менеджери контексту, щоб автоматично закривати їх:

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.

Якщо ви хочете , щоб написати заголовок у вихідний файл необробленого, який легко теж передавати висновок next()на writer.writerow():

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

22
Альтернативою також є використання, for row in islice(reader, 1, None)хоча менш чітке, ніж nextдля більшості простих завдань "пропустити один рядок", для пропуску декількох рядків заголовків (або отримання лише певних фрагментів тощо), це досить зручно
Джон Клементс

Я розглядаю можливість використанняtry: writer.write(next(reader))... except StopIteration: # handle empty reader
Джон Клементс

@JonClements: Можливо. Це працює досить добре, не вчити про try:/ except:.
Martijn Pieters

1
@JonClements: Перевага явної nextітерації в тому, що вона "безкоштовна"; isliceобернеться readerназавжди додаванням (мабуть, дуже невеликою кількістю) накладних витрат до кожної ітерації. consumeРецепт відitertools може бути використаний , щоб пропустити багато значень швидко, без додавання упаковки для подальшого використання, в тому випадку , якщо isliceне матиме , startале не end, так що накладні витрати не отримує нічого вам.
ShadowRanger

120

Інший спосіб вирішити це - використовувати клас DictReader, який "пропускає" рядок заголовка і використовує його для дозволеного індексованого індексу.

Подано "foo.csv" таким чином:

FirstColumn,SecondColumn
asdf,1234
qwer,5678

Використовуйте DictReader так:

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
Я відчуваю, що це справжня відповідь, оскільки це питання, здається, є прикладом проблеми XY .
MariusSiuram

3
DictReader - це точно дорога
Хав'єр Аріас

4
Важливо зауважити, що це працює лише в тому випадку, якщо під час побудови DictReader ви опустите параметр імен полів. Відповідно до документації: If the fieldnames parameter is omitted, the values in the first row of the file f will be used as the fieldnames.Див. Docs.python.org/2/library/csv.html
BuvinJ

7

Діяння row=1нічого не змінить, тому що ви просто перезаписаєте це з результатами циклу.

Ви хочете next(reader)пропустити один ряд.


Я спробував змінити його, for row in next(reader):але це дає мені IndexError: string index out of rangeпомилку

Використовуйте його перед циклом for: next(reader); for row in reader:....
dlazesz
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.