Ignore os cabeçalhos ao editar um arquivo CSV usando Python


209

Estou usando o código abaixo indicado para editar um csv usando Python. As funções chamadas no código formam a parte superior do código.

Problema: Desejo que o código abaixo mencionado comece a editar o csv da 2ª linha. Quero excluir a 1ª linha que contém os cabeçalhos. No momento, ele está aplicando as funções somente na 1ª linha e minha linha de cabeçalho está sendo alterada.

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

Tentei resolver esse problema inicializando a rowvariável para 1mas não funcionou.

Por favor, ajude-me a resolver esse problema.


Respostas:


370

Sua readervariável é iterável. Ao fazer o loop, você recupera as linhas.

Para fazer com que ele pule um item antes do loop, basta chamar next(reader, None)e ignorar o valor de retorno.

Você também pode simplificar um pouco o seu código; use os arquivos abertos como gerenciadores de contexto para fechá-los 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 você deseja gravar o cabeçalho no arquivo de saída não processado, também é fácil, passe a saída next()para writer.writerow():

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

22
Uma alternativa também é usar for row in islice(reader, 1, None)- embora seja menos explícito do que nextpara os trabalhos mais simples "pular uma linha", pular várias linhas de cabeçalho (ou obter apenas alguns trechos etc ...) é bastante útil
Jon Clements

Eu consideraria usandotry: writer.write(next(reader))... except StopIteration: # handle empty reader
Jon Clements

@ JonClements: Talvez. Isso funciona bem o suficiente sem ter que ensinar sobre try:/ except:.
Martijn Pieters

1
@ JonClements: A vantagem da nextiteração explícita é que ela é "gratuita"; isliceenvolveria a readeradição permanente (uma quantidade muito pequena de) de sobrecarga a cada iteração. A consumereceita deitertools pode ser usada para pular muitos valores rapidamente, sem adicionar empacotamento para uso subsequente, no caso em que isliceisso teria um startmas não end, para que a sobrecarga não esteja ganhando nada.
ShadowRanger

120

Outra maneira de resolver isso é usar a classe DictReader, que "ignora" a linha do cabeçalho e a usa para permitir a indexação nomeada.

Dado "foo.csv" da seguinte maneira:

FirstColumn,SecondColumn
asdf,1234
qwer,5678

Use o DictReader assim:

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
Eu sinto que esta é a resposta real, pois a pergunta parece ser um exemplo do problema XY .
MariusSiuram 23/09/16

3
DictReader é definitivamente o caminho a percorrer
Javier Arias

4
É importante observar que isso só funciona se você omitir o parâmetro de nomes de campo ao construir o DictReader. Pela documentação: If the fieldnames parameter is omitted, the values in the first row of the file f will be used as the fieldnames.Veja docs.python.org/2/library/csv.html
BuvinJ

7

Fazer row=1não mudará nada, porque você apenas substituirá isso pelos resultados do loop.

Você quer fazer next(reader)para pular uma linha.


Eu tentei alterá-lo para, for row in next(reader):mas está me dando um IndexError: string index out of rangeerro

Use-o antes do loop for: next(reader); for row in reader:....
dlazesz
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.