Ignorer les en-têtes lors de la modification d'un fichier csv à l'aide de Python

209

J'utilise ci-dessous le code référencé pour modifier un csv en utilisant Python. Les fonctions appelées dans le code forment la partie supérieure du code.

Problème: je veux que le code référencé ci-dessous commence à éditer le csv de la 2ème ligne, je veux qu'il exclue la 1ère ligne qui contient des en-têtes. En ce moment, il applique les fonctions sur la 1ère ligne uniquement et ma ligne d'en-tête est modifiée.

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

J'ai essayé de résoudre ce problème en initialisant la rowvariable à 1mais cela n'a pas fonctionné.

Veuillez m'aider à résoudre ce problème.

Martijn Pieters
la source

Réponses:

371

Votre readervariable est un itérable, en bouclant dessus vous récupérez les lignes.

Pour lui faire sauter un élément avant votre boucle, il suffit d'appeler next(reader, None)et d'ignorer la valeur de retour.

Vous pouvez également simplifier un peu votre code; utilisez les fichiers ouverts comme gestionnaires de contexte pour les fermer automatiquement:

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.

Si vous vouliez écrire l'en-tête dans le fichier de sortie non traité, c'est aussi facile, passez la sortie de next()à writer.writerow():

headers = next(reader, None)  # returns the headers or `None` if the input is empty
if headers:
    writer.writerow(headers)
Martijn Pieters
la source
22
Une alternative est également d'utiliser for row in islice(reader, 1, None)- bien que moins explicite que nextpour la plupart des travaux simples "sauter une ligne", pour sauter plusieurs lignes d'en-tête (ou obtenir seulement certains morceaux, etc.), c'est assez pratique
Jon Clements
J'envisagerais d'utilisertry: writer.write(next(reader))... except StopIteration: # handle empty reader
Jon Clements
@ JonClements: Peut-être. Cela fonctionne assez bien sans avoir à enseigner try:/ except:.
Martijn Pieters
1
@JonClements: L'avantage de l' nextitération explicite est qu'il est "gratuit"; isliceenvelopperait l' readerajout permanent (une quantité certes très faible) de frais généraux à chaque itération. La consumerecette deitertools peut être utilisée pour ignorer de nombreuses valeurs rapidement, sans ajouter d'habillage à une utilisation ultérieure, dans le cas où le isliceaurait un startmais non end, de sorte que la surcharge ne vous rapporte rien.
ShadowRanger
120

Une autre façon de résoudre ce problème consiste à utiliser la classe DictReader, qui «saute» la ligne d'en-tête et l'utilise pour autoriser l'indexation nommée.

Étant donné "foo.csv" comme suit:

FirstColumn,SecondColumn
asdf,1234
qwer,5678

Utilisez DictReader comme ceci:

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
la source
21
J'ai l'impression que c'est la vraie réponse, car la question semble être un exemple de problème XY .
MariusSiuram
3
DictReader est définitivement la voie à suivre
Javier Arias
4
Il est important de noter que cela ne fonctionne que si vous omettez le paramètre des noms de champ lors de la construction du DictReader. Selon la documentation: If the fieldnames parameter is omitted, the values in the first row of the file f will be used as the fieldnames.Voir docs.python.org/2/library/csv.html
BuvinJ
7

Faire row=1ne changera rien, car vous écraserez simplement cela avec les résultats de la boucle.

Vous voulez faire next(reader)pour sauter une ligne.

Katriel
la source
J'ai essayé de le changer en for row in next(reader):mais cela me donne une IndexError: string index out of rangeerreur
Utilisez-le avant la boucle for: next(reader); for row in reader:....
dlazesz