python - tutorial - El carácter EOF de Pandas ParserError al leer varios archivos csv en HDF5
read_csv pandas col index example (6)
Utilizando Python3, Pandas 0.12
Estoy intentando escribir varios archivos csv (el tamaño total es de 7.9 GB) en una tienda HDF5 para procesarlos más adelante. Los archivos csv contienen alrededor de un millón de filas cada una, 15 columnas y los tipos de datos son en su mayoría cadenas, pero algunos flotan. Sin embargo, cuando intento leer los archivos csv, aparece el siguiente error:
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
Editar :
Me las arreglé para encontrar un archivo que produjo este problema. Creo que está leyendo un personaje de EOF. Sin embargo no tengo ninguna pista para superar este problema. Dado el gran tamaño de los archivos combinados, creo que es demasiado engorroso comprobar cada carácter individual en cada cadena. (Incluso entonces no estaría seguro de qué hacer). En la medida en que lo verifiqué, no hay caracteres extraños en los archivos csv que puedan generar el error. También intenté pasar error_bad_lines=False
a pd.read_csv()
, pero el error persiste.
Mi código es el siguiente:
# -*- 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()
Editar
Si entro en el archivo CSV que genera el error de CParserError EOF ... y elimino manualmente todas las filas después de la línea que está causando el problema, el archivo csv se lee correctamente. Sin embargo, todo lo que estoy eliminando son filas en blanco de todos modos. Lo extraño es que cuando corrijo manualmente los archivos csv erróneos, se cargan bien en la tienda individualmente. Pero cuando vuelvo a usar una lista de varios archivos, los archivos "falsos" todavía me devuelven errores.
Haga su bucle interno de esta manera le permitirá detectar el archivo ''malo'' (y seguir investigando)
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
La solución es usar el parámetro engine = ''python'' en la función read_csv. El analizador Pandas CSV puede usar dos “motores” diferentes para analizar un archivo CSV: Python o C (que también es el valor predeterminado).
pandas.read_csv(filepath, sep='','', delimiter=None,
header=''infer'', names=None,
index_col=None, usecols=None, squeeze=False,
..., engine=None, ...)
El motor de Python se describe como " más lento, pero tiene más funciones completas " en la documentación de Pandas .
engine : {‘c’, ‘python’}
Me doy cuenta de que esta es una pregunta antigua, pero quería compartir algunos detalles más sobre la causa raíz de este error y por qué funciona la solución de @Selah.
De la csv.py
csv.py:
* 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
es el valor predeterminado y "
es el quotechar
predeterminado. Si en algún lugar de su archivo csv tiene un quotechar, se analizará como una cadena hasta que aparezca otro quot. no debe cerrarse antes de alcanzar el EOF
(final del archivo). También tenga en cuenta que cualquier cosa entre comillas se analizará como una sola cadena. Incluso si hay muchos saltos de línea (se espera que se analicen como filas separadas), todo se convierte en una campo único de la tabla. Por lo tanto, el número de línea que recibe en el error puede ser engañoso. Para ilustrar con un ejemplo, considere esto:
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 primera cadena tiene 2 (par) quotechars. Por lo tanto, cada quotechar se cierra y el csv se analiza sin error, aunque probablemente no sea lo que esperábamos. La otra cadena tiene 3 cotillas (impares). El último no se cierra y se alcanza el EOF, de ahí el error. Pero la línea 2 que recibimos en el mensaje de error es engañosa. Esperamos 4, pero dado que todo entre la primera y la segunda cotización se analiza como una cadena, nuestra línea "p,q,r
es realmente la segunda.
Para mí, las otras soluciones no funcionaron y me causaron un gran dolor de cabeza. error_bad_lines = False todavía da el error C error: EOF inside string starting at line
. Usar una cita diferente tampoco dio los resultados deseados, ya que no quería tener citas en mi texto.
Me di cuenta de que había un error en Pandas 0.20. La actualización a la versión 0.21 resolvió por completo mi problema. Más información sobre este error, consulte: https://github.com/pandas-dev/pandas/issues/16559
Nota: esto puede estar relacionado con Windows como se menciona en la URL.
Tengo el mismo problema, y después de agregar estos dos parámetros a mi código, el problema desapareció.
read_csv (...
quoting=3
,error_bad_lines=False
)
Tuve un problema similar. La línea listada con el ''EOF dentro de la cadena'' tenía una cadena que contenía una comilla simple. Cuando agregué la opción quoting = csv.QUOTE_NONE, solucioné mi problema.
Por ejemplo:
import csv
df = pd.read_csv(csvfile, header = None, delimiter="/t", quoting=csv.QUOTE_NONE, encoding=''utf-8'')