Пропустить заголовки при редактировании файла 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но это не сработало.

Пожалуйста, помогите мне в решении этой проблемы.

Мартейн Питерс
источник

Ответы:

371

Ваша 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:.
Мартин Питерс
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)чтобы пропустить один ряд.

Katriel
источник
Я пытался изменить его на, for row in next(reader):но это дает мне IndexError: string index out of rangeошибку
Используйте его перед циклом for: next(reader); for row in reader:....
dlazesz