web-dev-qa-db-fra.com

Python: ignorer les lignes de commentaires marquées d'un # dans csv.DictReader

Le traitement des fichiers CSV avec csv.DictReader est génial - mais j'ai des fichiers CSV avec des lignes de commentaires (indiqué par un hachage au début d'une ligne), par exemple:

 # taille de pas = 1,61853 
 val0, val1, val2, hybridation, temp, smattr 
 0.206895,0.797923,0.202077,0.631199,0.368801,0.311052,0.688948,0.597237,0.402763 
 - 169,32,1,1,61853,2.04069e-92,1,0,000906546,0,999093,0.241356,0.758644,0.202382 
 # Adaptation terminée 

Le module csv n'inclut aucun moyen de sauter de telles lignes .

Je pourrais facilement faire quelque chose de hacky, mais j'imagine qu'il y a une belle façon d'enrouler un csv.DicReader autour d'un autre objet itérateur, qui pré-traite pour éliminer les lignes.

60
Dan Stowell

En fait, cela fonctionne bien avec filter:

import csv
fp = open('samples.csv')
rdr = csv.DictReader(filter(lambda row: row[0]!='#', fp))
for row in rdr:
    print(row)
fp.close()
78
Dan Stowell

Bonne question et un bon exemple de la façon dont la bibliothèque CSV de Python manque de fonctionnalités importantes, telles que la gestion des commentaires de base (ce qui n'est pas rare en haut des fichiers CSV). Bien que la solution de Dan Stowell fonctionne pour le cas spécifique de l'OP, elle est limitée en ce que # Doit apparaître comme premier symbole. Une solution plus générique serait:

def decomment(csvfile):
    for row in csvfile:
        raw = row.split('#')[0].strip()
        if raw: yield raw

with open('dummy.csv') as csvfile:
    reader = csv.reader(decomment(csvfile))
    for row in reader:
        print(row)

Par exemple, le fichier dummy.csv Suivant:

# comment
 # comment
a,b,c # comment
1,2,3
10,20,30
# comment

retour

['a', 'b', 'c']
['1', '2', '3']
['10', '20', '30']

Bien sûr, cela fonctionne aussi bien avec csv.DictReader().

5
sigvaldm

Une autre façon de lire un fichier CSV est d'utiliser pandas

Voici un exemple de code:

df = pd.read_csv('test.csv',
                 sep=',',     # field separator
                 comment='#', # comment
                 index_col=0, # number or label of index column
                 skipinitialspace=True,
                 skip_blank_lines=True,
                 error_bad_lines=False,
                 warn_bad_lines=True
                 ).sort_index()
print(df)
df.fillna('no value', inplace=True) # replace NaN with 'no value'
print(df)

Pour ce fichier csv:

a,b,c,d,e
1,,16,,55#,,65##77
8,77,77,,16#86,18#
#This is a comment
13,19,25,28,82

nous obtiendrons cette sortie:

       b   c     d   e
a                     
1    NaN  16   NaN  55
8   77.0  77   NaN  16
13  19.0  25  28.0  82
           b   c         d   e
a                             
1   no value  16  no value  55
8         77  77  no value  16
13        19  25        28  82
2
Granny Aching