web-dev-qa-db-fra.com

Pandas ParserError EOF Caractère lors de la lecture de plusieurs fichiers CSV sur HDF5

Utiliser Python3, Pandas 0.12

J'essaie d'écrire plusieurs fichiers csv (la taille totale est de 7,9 Go) dans un magasin HDF5 pour traitement ultérieur. Les fichiers csv contiennent environ un million de lignes chacune, 15 colonnes et les types de données sont principalement des chaînes, mais certains flottent. Cependant, lorsque j'essaie de lire les fichiers csv, l'erreur suivante apparaît:

Traceback (most recent call last):
  File "filter-1.py", line 38, in <module>
    to_hdf()
  File "filter-1.py", line 31, in to_hdf
    for chunk in reader:
  File "C:\Python33\lib\site-packages\pandas\io\parsers.py", line 578, in __iter__
    yield self.read(self.chunksize)
  File "C:\Python33\lib\site-packages\pandas\io\parsers.py", line 608, in read
    ret = self._engine.read(nrows)
  File "C:\Python33\lib\site-packages\pandas\io\parsers.py", line 1028, in read
    data = self._reader.read(nrows)
  File "parser.pyx", line 706, in pandas.parser.TextReader.read (pandas\parser.c:6745)
  File "parser.pyx", line 740, in pandas.parser.TextReader._read_low_memory (pandas\parser.c:7146)
  File "parser.pyx", line 781, in pandas.parser.TextReader._read_rows (pandas\parser.c:7568)
  File "parser.pyx", line 768, in pandas.parser.TextReader._tokenize_rows (pandas\parser.c:7451)
  File "parser.pyx", line 1661, in pandas.parser.raise_parser_error (pandas\parser.c:18744)
pandas.parser.CParserError: Error tokenizing data. C error: EOF inside string starting at line 754991
Closing remaining open files: ta_store.h5... done 

Modifier :

J'ai réussi à trouver un fichier qui a provoqué ce problème. Je pense que c'est lire un caractère EOF. Cependant, je n'ai aucune idée pour surmonter ce problème. Compte tenu de la grande taille des fichiers combinés, je trouve trop fastidieux de vérifier chaque caractère de chaque chaîne. (Même dans ce cas, je ne serais toujours pas sûr de savoir quoi faire.) Pour autant que j'ai vérifié, il n'y a pas de caractères étranges dans les fichiers csv qui pourraient générer l'erreur. J'ai aussi essayé de passer de error_bad_lines=False à pd.read_csv() l'erreur persiste.

Mon code est le suivant:

# -*- coding: utf-8 -*-

import pandas as pd
import os
from glob import glob


def list_files(path=os.getcwd()):
    ''' List all files in specified path '''
    list_of_files = [f for f in glob('2013-06*.csv')]
    return list_of_files


def to_hdf():
    """ Function that reads multiple csv files to HDF5 Store """
    # Defining path name
    path = 'ta_store.h5'
    # If path exists delete it such that a new instance can be created
    if os.path.exists(path):
        os.remove(path)
    # Creating HDF5 Store
    store = pd.HDFStore(path)

    # Reading csv files from list_files function
    for f in list_files():
        # Creating reader in chunks -- reduces memory load
        reader = pd.read_csv(f, chunksize=50000)
        # Looping over chunks and storing them in store file, node name 'ta_data'
        for chunk in reader:
            chunk.to_hdf(store, 'ta_data', mode='w', table=True)

    # Return store
    return store.select('ta_data')
    return 'Finished reading to HDF5 Store, continuing processing data.'

to_hdf()

Modifier

Si je vais dans le fichier CSV qui soulève le fichier CParserError EOF ... et supprime manuellement toutes les lignes après la ligne à l'origine du problème, le fichier csv est lu correctement. Cependant, tout ce que je supprime, ce sont des lignes vierges de toute façon. Ce qui est étrange, c'est que lorsque je corrige manuellement les fichiers CSV erronés, ils sont chargés individuellement dans le magasin. Mais lorsque j'utilise à nouveau une liste de plusieurs fichiers, les «faux» fichiers me renvoient toujours des erreurs.

16
Matthijs

J'avais un problème similaire. La ligne répertoriée avec 'EOF inside string' contenait une chaîne contenant un guillemet simple. Lorsque j'ai ajouté l'option citant = csv.QUOTE_NONE, mon problème a été résolu.

Par exemple:

import csv
df = pd.read_csv(csvfile, header = None, delimiter="\t", quoting=csv.QUOTE_NONE, encoding='utf-8')
61
Selah

J'ai le même problème, et après avoir ajouté ces deux paramètres à mon code, le problème a disparu.

read_csv (...quoting=3, error_bad_lines=False)

11
weefwefwqg3

Faites en sorte que votre boucle interne vous permette de détecter le «mauvais» fichier (et d’enquêter davantage)

from pandas.io import parser

def to_hdf():

    .....

    # Reading csv files from list_files function
    for f in list_files():
        # Creating reader in chunks -- reduces memory load

        try:

            reader = pd.read_csv(f, chunksize=50000)

            # Looping over chunks and storing them in store file, node name 'ta_data'
            for chunk in reader:
                chunk.to_hdf(store, 'ta_data', table=True)

        except (parser.CParserError) as detail:
             print f, detail
5
Jeff

La solution consiste à utiliser le paramètre engine = ’python’ dans la fonction read_csv. L'analyseur CSV de Pandas peut utiliser deux "moteurs" différents pour analyser un fichier CSV - Python ou C (qui est également le paramètre par défaut).

pandas.read_csv(filepath, sep=',', delimiter=None, 
            header='infer', names=None, 
            index_col=None, usecols=None, squeeze=False, 
            ..., engine=None, ...)

Le moteur Python est décrit comme étant « plus lent, mais est plus complet » dans la documentation Pandas .

engine : {‘c’, ‘python’}
3
Aman Singh

Je réalise que c’est une vieille question, mais je voulais partager quelques détails supplémentaires sur la cause première de cette erreur et sur la raison pour laquelle la solution de @Selah fonctionne. 

De la csv.py docstring:

    * quoting - controls when quotes should be generated by the writer.
    It can take on any of the following module constants:

    csv.QUOTE_MINIMAL means only when required, for example, when a
        field contains either the quotechar or the delimiter
    csv.QUOTE_ALL means that quotes are always placed around fields.
    csv.QUOTE_NONNUMERIC means that quotes are always placed around
        fields which do not parse as integers or floating point
        numbers.
    csv.QUOTE_NONE means that quotes are never placed around fields.

csv.QUOTE_MINIMAL est la valeur par défaut et " la valeur par défaut quotechar. Si quelque part dans votre fichier csv vous avez un quotechar, il sera analysé comme une chaîne jusqu'à une autre occurrence du quotechar. Si votre fichier contient un nombre impair de cotes, le dernier ne sera pas fermé avant d'atteindre la EOF (fin du fichier). Sachez également que tout ce qui se trouve entre les cotes sera analysé comme une seule chaîne. Même s'il existe de nombreux sauts de ligne (susceptibles d'être analysés sous forme de lignes séparées), tout se trouve dans un seul champ de la table. Ainsi, le numéro de ligne que vous obtenez dans l'erreur peut être trompeur. Pour illustrer avec un exemple, considérons ceci:

In[4]: import pandas as pd
  ...: from io import StringIO
  ...: test_csv = '''a,b,c
  ...: "d,e,f
  ...: g,h,i
  ...: "m,n,o
  ...: p,q,r
  ...: s,t,u
  ...: '''
  ...: 
In[5]: test = StringIO(test_csv)
In[6]: pd.read_csv(test)
Out[6]: 
                 a  b  c
0  d,e,f\ng,h,i\nm  n  o
1                p  q  r
2                s  t  u
In[7]: test_csv_2 = '''a,b,c
  ...: "d,e,f
  ...: g,h,i
  ...: "m,n,o
  ...: "p,q,r
  ...: s,t,u
  ...: '''
  ...: test_2 = StringIO(test_csv_2)
  ...: 
In[8]: pd.read_csv(test_2)
Traceback (most recent call last):
...
...
pandas.errors.ParserError: Error tokenizing data. C error: EOF inside string starting at line 2

La première chaîne a 2 quotes (pairs). Donc, chaque quotechar est fermé et le csv est analysé sans erreur, bien que ce ne soit probablement pas ce à quoi nous nous attendions. L'autre chaîne a 3 quotés (impairs). Le dernier n'est pas fermé et le EOF est atteint d'où l'erreur. Mais la ligne 2 que nous recevons dans le message d'erreur est trompeuse. Nous nous en attendions à 4, mais comme tout ce qui se situe entre le premier et le deuxième quotechar est analysé comme une chaîne, notre ligne "p,q,r est en fait seconde.

2
MJB

Pour moi, les autres solutions ne fonctionnaient pas et me causaient beaucoup de maux de tête. error_bad_lines = False donne toujours l'erreur C error: EOF inside string starting at line. Utiliser une citation différente ne donnait pas non plus les résultats souhaités, car je ne voulais pas avoir de citations dans mon texte.

J'ai réalisé qu'il y avait un bug dans Pandas 0.20. La mise à niveau vers la version 0.21 a complètement résolu mon problème. Plus d'infos sur ce bug, voir: https://github.com/pandas-dev/pandas/issues/16559

Remarque: cela peut être lié à Windows, comme indiqué dans l'URL.

0
Guido