Python Pandas Error al tokenizar datos

341

Estoy tratando de usar pandas para manipular un archivo .csv pero aparece este error:

pandas.parser.CParserError: error al tokenizar datos. Error C: se esperaban 2 campos en la línea 3, vi 12

Intenté leer los documentos de los pandas, pero no encontré nada.

Mi código es simple:

path = 'GOOG Key Ratios.csv'
#print(open(path).read())
data = pd.read_csv(path)

¿Cómo puedo resolver esto? ¿Debo usar el csvmódulo u otro idioma?

El archivo es de Morningstar

abuteau
fuente
10
Si surge este error al leer un archivo escrito por pandas.to_csv(), PUEDE ser porque hay un '\ r' en los nombres de las columnas, en cuyo caso to_csv () realmente escribirá los nombres de las columnas posteriores en la primera columna del marco de datos, causando Una diferencia entre el número de columnas en las primeras X filas. Esta diferencia es una de las causas del error C.
usuario0
8
En algún momento, solo ayuda explícitamente dar el parámetro "sep". Parece ser un problema de analizador.
gilgamash
2
Este error también puede surgir cuando usa una coma como delimitador y tiene más comas de las esperadas (más campos en la fila de error y luego definidos en el encabezado). Por lo tanto, debe eliminar el campo adicional o eliminar la coma adicional si está allí por error. Puede arreglar esto manualmente y luego no necesita omitir las líneas de error.
tsveti_iko
2
El comentario de Gilgamash me ayudó. Abra el archivo csv en un editor de texto (como el editor de Windows o el bloc de notas ++) para ver qué carácter se utiliza para la separación. Si es un punto y coma, por ejemplo, inténtalo pd.read_csv("<path>", sep=";"). No use Excel para verificar, ya que a veces coloca los datos en columnas de forma predeterminada y, por lo tanto, elimina el separador.
Julian
Con respecto al comentario de @gilgamash, esto me envió en la dirección correcta, sin embargo, en mi caso, se resolvió explícitamente al no dar el parámetro "sep".
TheLoneDeranger

Respuestas:

514

también podrías intentarlo;

data = pd.read_csv('file1.csv', error_bad_lines=False)

Tenga en cuenta que esto hará que se salten las líneas ofensivas.

Richie
fuente
152
Tenga en cuenta que el uso de error_bad_lines = False hará que se omitan las líneas ofensivas.
biobirdman
10
Tropezado con esta respuesta, ¿hay alguna manera de llenar las columnas que faltan en las líneas que generan algo así expected 8 fields, saw 9?
Petra Barus
26
La mejor solución es investigar el archivo ofensivo y corregir las líneas incorrectas para que puedan ser leídas read_csv. @PetraBarus, ¿por qué no solo agregar columnas a los archivos CSV que les faltan (con valores nulos según sea necesario)?
dbliss
44
Sí, acabo de hacer eso. Es mucho más fácil agregar columnas. Abrir CSV en una hoja de cálculo hace esto.
Petra Barus
55
Pasar names=["col1", "col2", ...]por el número máximo de columnas esperadas también funciona, y así es como resolví este problema cuando lo encontré. Ver: stackoverflow.com/questions/18039057/…
Steven Rouk
99

Puede ser un problema con

  • los delimitadores en sus datos
  • la primera fila, como señaló @TomAugspurger

Para resolverlo, intente especificar los argumentos sepy / o headercuando llame read_csv. Por ejemplo,

df = pandas.read_csv(fileName, sep='delimiter', header=None)

En el código anterior, sepdefine su delimitador y header=Nonele dice a los pandas que sus datos de origen no tienen fila para encabezados / títulos de columna. Así dice los documentos : "Si el archivo no contiene una fila de encabezado, entonces debe pasar explícitamente encabezado = Ninguno". En este caso, pandas crea automáticamente índices de números enteros para cada campo {0,1,2, ...}.

De acuerdo con los documentos, lo delimitador debe no ser un problema. Los documentos dicen que "si sep es None [no especificado], intentará determinar esto automáticamente". Sin embargo, no he tenido buena suerte con esto, incluidas instancias con delimitadores obvios.

grisaitis
fuente
Sí, a veces el delimitador puede ser la causa de este problema. Me enfrenté al mismo problema donde el delimitador era un punto y coma (;)
Anurag Sharma
43

El encabezado del archivo está confundiendo el analizador. Lee la primera fila e infiere el número de columnas de esa fila. Pero las dos primeras filas no son representativas de los datos reales en el archivo.

Pruébalo con data = pd.read_csv(path, skiprows=2)

TomAugspurger
fuente
30

Su archivo CSV podría tener un número variable de columnas e read_csvinferir el número de columnas de las primeras filas. Dos formas de resolverlo en este caso:

1) Cambie el archivo CSV para que tenga una primera línea ficticia con un número máximo de columnas (y especifique header=[0])

2) O use names = list(range(0,N))donde N es el número máximo de columnas.

informático
fuente
24

Este es definitivamente un problema de delimitador, ya que la mayoría de los CSV CSV se crean usando, sep='/t'así que intente read_csvusar el carácter de tabulación (\t)con separador /t. entonces, intente abrir usando la siguiente línea de código.

data=pd.read_csv("File_path", sep='\t')
Piyush S. Wanare
fuente
55
@MichaelQueue: Esto es incorrecto. Un CSV, aunque comúnmente está delimitado por una coma, también puede estar delimitado por otros caracteres. Ver especificaciones CSV . Puede ser una coma, una pestaña ('\ t'), punto y coma y posiblemente espacios adicionales. :)
DJGrandpaJ
en mi caso fue un problema de separación. El valor predeterminado de read_csv es comas, y tengo campos de texto que incluyen comas (y los datos se almacenaron con un separador diferente de todos modos)
user108569
Si se usan comas en los valores, pero tab es el delimitador y sep no se usa (o como se sugiere arriba de los delimitadores, lo que se supone que ocurre en los valores), entonces se producirá este error. Asegúrese de que el delimitador no aparezca en ninguno de los valores; de lo contrario, algunas filas parecerán tener un número incorrecto de columnas
demongolem
Estoy usando Excel 2016 al crear el CSV, y estoy usando sep = ';' trabaja para mí
Abdullah dijo el
18

También tuve este problema, pero tal vez por una razón diferente. Tenía algunas comas finales en mi CSV que agregaban una columna adicional que los pandas intentaban leer. Usando los siguientes trabajos pero simplemente ignora las líneas malas:

data = pd.read_csv('file1.csv', error_bad_lines=False)

Si desea mantener las líneas, un tipo de truco feo para manejar los errores es hacer algo como lo siguiente:

line     = []
expected = []
saw      = []     
cont     = True 

while cont == True:     
    try:
        data = pd.read_csv('file1.csv',skiprows=line)
        cont = False
    except Exception as e:    
        errortype = e.message.split('.')[0].strip()                                
        if errortype == 'Error tokenizing data':                        
           cerror      = e.message.split(':')[1].strip().replace(',','')
           nums        = [n for n in cerror.split(' ') if str.isdigit(n)]
           expected.append(int(nums[0]))
           saw.append(int(nums[2]))
           line.append(int(nums[1])-1)
         else:
           cerror      = 'Unknown'
           print 'Unknown Error - 222'

if line != []:
    # Handle the errors however you want

Procedí a escribir un script para reinsertar las líneas en el DataFrame ya que las líneas incorrectas serán dadas por la variable 'línea' en el código anterior. Todo esto se puede evitar simplemente usando el lector csv. Esperemos que los desarrolladores de pandas puedan facilitar el manejo de esta situación en el futuro.

Robert Geiger
fuente
14

Tuve este problema, cuando estaba tratando de leer un CSV sin pasar los nombres de columna.

df = pd.read_csv(filename, header=None)

Especifiqué los nombres de columna en una lista de antemano y luego los pasé names, y lo resolvió de inmediato. Si no ha establecido los nombres de las columnas, puede crear tantos nombres de marcador de posición como el número máximo de columnas que puedan estar en sus datos.

col_names = ["col1", "col2", "col3", ...]
df = pd.read_csv(filename, names=col_names)
Steven Rouk
fuente
1
Esta respuesta es mejor porque la fila no se elimina en comparación con si usa error_bad_line = False. Además, puede averiguar fácilmente qué líneas fueron las problemáticas una vez que hicieron un marco de datos a partir de esta solución.
zipline86
Estoy de acuerdo con @ zipline86. Esta respuesta es segura e inteligente.
Monica Heddneck
11

He tenido este problema varias veces. Casi siempre, la razón es que el archivo que intentaba abrir no era un CSV guardado correctamente para empezar. Y por "correctamente", quiero decir que cada fila tenía el mismo número de separadores o columnas.

Por lo general, sucedió porque abrí el archivo CSV en Excel y luego lo guardé incorrectamente. Aunque la extensión del archivo todavía era .csv, el formato CSV puro había sido alterado.

Cualquier archivo guardado con pandas to_csv se formateará correctamente y no debería tener ese problema. Pero si lo abre con otro programa, puede cambiar la estructura.

Espero que ayude.

elPastor
fuente
8

Me encontré con el mismo problema. El uso pd.read_table()en el mismo archivo fuente parecía funcionar. No pude rastrear la razón de esto, pero fue una solución útil para mi caso. Quizás alguien más conocedor pueda arrojar más luz sobre por qué funcionó.

Editar: descubrí que este error aparece cuando tienes texto en tu archivo que no tiene el mismo formato que los datos reales. Esta suele ser información de encabezado o pie de página (más de una línea, por lo que skip_header no funciona) que no estará separada por la misma cantidad de comas que sus datos reales (cuando use read_csv). El uso de read_table usa una pestaña como delimitador que podría eludir el error actual de los usuarios pero introducir otros.

Por lo general, evito esto leyendo los datos adicionales en un archivo y luego uso el método read_csv ().

La solución exacta puede variar según el archivo real, pero este enfoque me ha funcionado en varios casos.

Legend_Ari
fuente
6

Lo siguiente funcionó para mí (publiqué esta respuesta, porque específicamente tuve este problema en un cuaderno de colaboración de Google):

df = pd.read_csv("/path/foo.csv", delimiter=';', skiprows=0, low_memory=False)
Puñal
fuente
1
Experimenté problemas al no establecer |como delimitador para mi .csv. Prefiero probar este enfoque primero, en lugar de omitir líneas o líneas incorrectas.
ivanleoncz
También tuve el mismo problema, supuse que "\ t" se detectaría como delimitador de forma predeterminada. Funcionó cuando configuré explícitamente el delimitador a "\ t".
Rahul Jha
5

Tuve un problema similar al intentar leer una tabla delimitada por tabulaciones con espacios, comas y comillas:

1115794 4218    "k__Bacteria", "p__Firmicutes", "c__Bacilli", "o__Bacillales", "f__Bacillaceae", ""
1144102 3180    "k__Bacteria", "p__Firmicutes", "c__Bacilli", "o__Bacillales", "f__Bacillaceae", "g__Bacillus", ""
368444  2328    "k__Bacteria", "p__Bacteroidetes", "c__Bacteroidia", "o__Bacteroidales", "f__Bacteroidaceae", "g__Bacteroides", ""



import pandas as pd
# Same error for read_table
counts = pd.read_csv(path_counts, sep='\t', index_col=2, header=None, engine = 'c')

pandas.io.common.CParserError: Error tokenizing data. C error: out of memory

Esto dice que tiene algo que ver con el motor de análisis C (que es el predeterminado). Tal vez cambiar a Python One cambiará cualquier cosa

counts = pd.read_table(path_counts, sep='\t', index_col=2, header=None, engine='python')

Segmentation fault (core dumped)

Ahora que es un error diferente.
Si seguimos adelante e intentamos eliminar espacios de la tabla, el error de python-engine cambia una vez más:

1115794 4218    "k__Bacteria","p__Firmicutes","c__Bacilli","o__Bacillales","f__Bacillaceae",""
1144102 3180    "k__Bacteria","p__Firmicutes","c__Bacilli","o__Bacillales","f__Bacillaceae","g__Bacillus",""
368444  2328    "k__Bacteria","p__Bacteroidetes","c__Bacteroidia","o__Bacteroidales","f__Bacteroidaceae","g__Bacteroides",""


_csv.Error: '   ' expected after '"'

Y queda claro que los pandas tenían problemas para analizar nuestras filas. Para analizar una tabla con el motor Python, necesitaba eliminar todos los espacios y comillas de la tabla de antemano. Mientras tanto, C-engine seguía fallando incluso con comas en filas.

Para evitar crear un nuevo archivo con reemplazos, hice esto, ya que mis tablas son pequeñas:

from io import StringIO
with open(path_counts) as f:
    input = StringIO(f.read().replace('", ""', '').replace('"', '').replace(', ', ',').replace('\0',''))
    counts = pd.read_table(input, sep='\t', index_col=2, header=None, engine='python')

tl; dr
Cambie el motor de análisis, intente evitar comillas / comas / espacios no delimitadores en sus datos.

lotrus28
fuente
5

El conjunto de datos que utilicé tenía muchas comillas (") ajenas al formato. Pude corregir el error al incluir este parámetro para read_csv():

quoting=3 # 3 correlates to csv.QUOTE_NONE for pandas
usuario3426943
fuente
2
tropecé con exactamente lo mismo. En lo que a mí respecta, esta es la respuesta correcta. El aceptado simplemente oculta el error.
lhk
Respuesta correcta para mí también. +1
Taha Jirjees
4

Usar delimitador en el parámetro

pd.read_csv(filename, delimiter=",", encoding='utf-8')

Leerá

Bhavesh Kumar
fuente
3

Aunque no es el caso para esta pregunta, este error también puede aparecer con datos comprimidos. Establecer explícitamente el valor para kwarg compressionresolver mi problema.

result = pandas.read_csv(data_source, compression='gzip')
Programación programada regularmente
fuente
3

Una alternativa que he encontrado útil para tratar errores de análisis similares utiliza el módulo CSV para redirigir los datos a un pandas df. Por ejemplo:

import csv
import pandas as pd
path = 'C:/FileLocation/'
file = 'filename.csv'
f = open(path+file,'rt')
reader = csv.reader(f)

#once contents are available, I then put them in a list
csv_list = []
for l in reader:
    csv_list.append(l)
f.close()
#now pandas has no problem getting into a df
df = pd.DataFrame(csv_list)

Creo que el módulo CSV es un poco más robusto que los archivos separados por comas mal formateados y, por lo tanto, he tenido éxito con esta ruta para abordar problemas como estos.

bcoz
fuente
3

La siguiente secuencia de comandos funciona (pierdo la primera línea de datos -no encabezado = Ninguno presente-, pero al menos se carga):

df = pd.read_csv(filename, usecols=range(0, 42)) df.columns = ['YR', 'MO', 'DAY', 'HR', 'MIN', 'SEC', 'HUND', 'ERROR', 'RECTYPE', 'LANE', 'SPEED', 'CLASS', 'LENGTH', 'GVW', 'ESAL', 'W1', 'S1', 'W2', 'S2', 'W3', 'S3', 'W4', 'S4', 'W5', 'S5', 'W6', 'S6', 'W7', 'S7', 'W8', 'S8', 'W9', 'S9', 'W10', 'S10', 'W11', 'S11', 'W12', 'S12', 'W13', 'S13', 'W14']

Lo siguiente NO funciona:

df = pd.read_csv(filename, names=['YR', 'MO', 'DAY', 'HR', 'MIN', 'SEC', 'HUND', 'ERROR', 'RECTYPE', 'LANE', 'SPEED', 'CLASS', 'LENGTH', 'GVW', 'ESAL', 'W1', 'S1', 'W2', 'S2', 'W3', 'S3', 'W4', 'S4', 'W5', 'S5', 'W6', 'S6', 'W7', 'S7', 'W8', 'S8', 'W9', 'S9', 'W10', 'S10', 'W11', 'S11', 'W12', 'S12', 'W13', 'S13', 'W14'], usecols=range(0, 42))

CParserError: error al tokenizar datos. Error C: se esperaban 53 campos en la línea 1605634, se vieron 54 Los siguientes NO funcionan:

df = pd.read_csv(filename, header=None)

CParserError: error al tokenizar datos. Error C: se esperaban 53 campos en la línea 1605634, vi 54

Por lo tanto, en tu problema tienes que pasar usecols=range(0, 2)

kepy97
fuente
3

Para aquellos que tienen un problema similar con Python 3 en el sistema operativo Linux.

pandas.errors.ParserError: Error tokenizing data. C error: Calling
read(nbytes) on source failed. Try engine='python'.

Tratar:

df.read_csv('file.csv', encoding='utf8', engine='python')
Zstack
fuente
2

A veces, el problema no es cómo usar Python, sino con los datos sin procesar.
Recibí este mensaje de error

Error tokenizing data. C error: Expected 18 fields in line 72, saw 19.

Resultó que en la descripción de la columna a veces había comas. Esto significa que es necesario limpiar el archivo CSV o utilizar otro separador.

Kims Sifers
fuente
1

Tenía un conjunto de datos con números de fila preexistentes, utilicé index_col:

pd.read_csv('train.csv', index_col=0)
gogasca
fuente
1

Esto es lo que hice.

sep='::' resuelto mi problema:

data=pd.read_csv('C:\\Users\\HP\\Downloads\\NPL ASSINGMENT 2 imdb_labelled\\imdb_labelled.txt',engine='python',header=None,sep='::')
Saurabh Tripathi
fuente
1

Tuve un caso similar a este y la configuración

train = pd.read_csv('input.csv' , encoding='latin1',engine='python') 

trabajó

Adewole Adesola
fuente
1

Tengo el mismo problema cuando read_csv: ParserError: error al tokenizar datos. Acabo de guardar el viejo archivo csv en un nuevo archivo csv. ¡El problema esta resuelto!

Simin Zuo
fuente
1

El problema para mí fue que se agregó una nueva columna a mi CSV intradía . La solución de respuesta aceptada no funcionaría como cada fila futura se descartaría si la usara error_bad_lines=False.

La solución en este caso fue usar el parámetro usecols en pd.read_csv(). De esta manera, puedo especificar solo las columnas que necesito leer en el CSV y mi código de Python seguirá siendo resistente a futuros cambios de CSV siempre que exista una columna de encabezado (y los nombres de las columnas no cambien).

usecols : list-like or callable, optional 

Return a subset of the columns. If list-like, all elements must either
be positional (i.e. integer indices into the document columns) or
strings that correspond to column names provided either by the user in
names or inferred from the document header row(s). For example, a
valid list-like usecols parameter would be [0, 1, 2] or ['foo', 'bar',
'baz']. Element order is ignored, so usecols=[0, 1] is the same as [1,
0]. To instantiate a DataFrame from data with element order preserved
use pd.read_csv(data, usecols=['foo', 'bar'])[['foo', 'bar']] for
columns in ['foo', 'bar'] order or pd.read_csv(data, usecols=['foo',
'bar'])[['bar', 'foo']] for ['bar', 'foo'] order.

Ejemplo

my_columns = ['foo', 'bar', 'bob']
df = pd.read_csv(file_path, usecols=my_columns)

Otro beneficio de esto es que puedo cargar menos datos en la memoria si solo estoy usando 3-4 columnas de un CSV que tiene 18-20 columnas.

Scott Skiles
fuente
1

Resolución simple : abra el archivo csv en excel y guárdelo con un archivo de nombre diferente en formato csv. Nuevamente intente importarlo spyder, ¡Su problema será resuelto!

Naseer
fuente
1

He encontrado este error con una comilla perdida. Utilizo un software de mapeo que pondrá comillas alrededor de los elementos de texto al exportar archivos delimitados por comas. El texto que utiliza comillas (p. Ej., '= Pies y "= pulgadas) puede ser problemático cuando induce colisiones del delimitador. Considere este ejemplo que señala que una impresión de registro de pozo de 5 pulgadas es deficiente:

UWI_key,Latitude,Longitude,Remark US42051316890000,30.4386484,-96.4330734,"poor 5""

Utilizando 5" como taquigrafía para 5 inchterminar tirando una llave inglesa en las obras. Excel simplemente eliminará las comillas adicionales, pero Pandas se descompone sin el error_bad_lines=Falseargumento mencionado anteriormente.

Andrew Silver
fuente
1

Por lo que puedo decir, y después de echar un vistazo a su archivo, el problema es que el archivo csv que está intentando cargar tiene varias tablas. Hay líneas vacías o líneas que contienen títulos de tabla. Intenta echar un vistazo a esto respuesta de Stackoverflow . Muestra cómo lograr eso mediante programación.

Otro enfoque dinámico para hacerlo sería utilizar el módulo csv , leer cada fila a la vez y realizar comprobaciones de cordura / expresiones regulares, para inferir si la fila es (título / encabezado / valores / en blanco). Tiene una ventaja más con este enfoque, que puede dividir / agregar / recopilar sus datos en objetos de python según lo desee.

Lo más fácil de todo sería usar la función de pandas pd.read_clipboard()después de seleccionar y copiar manualmente la tabla en el portapapeles, en caso de que pueda abrir el csv en Excel o algo así.

Irrelevante :

Además, es irrelevante para su problema, pero debido a que nadie mencionó esto : tuve este mismo problema al cargar algunos conjuntos de datos como seeds_dataset.txtUCI. En mi caso, el error estaba ocurriendo porque algunos separadores tenían más espacios en blanco que una pestaña verdadera \t. Vea la línea 3 a continuación, por ejemplo

14.38   14.21   0.8951  5.386   3.312   2.462   4.956   1
14.69   14.49   0.8799  5.563   3.259   3.586   5.219   1
14.11   14.1    0.8911  5.42    3.302   2.7     5       1

Por lo tanto, use \t+en el patrón separador en lugar de \t.

data = pd.read_csv(path, sep='\t+`, header=None)
Kareem Jeiroudi
fuente
1

En mi caso, es porque el formato de las dos primeras y últimas líneas del archivo csv es diferente del contenido del medio del archivo.

Entonces, lo que hago es abrir el archivo csv como una cadena, analizar el contenido de la cadena y luego usarlo read_csvpara obtener un marco de datos.

import io
import pandas as pd

file = open(f'{file_path}/{file_name}', 'r')
content = file.read()

# change new line character from '\r\n' to '\n'
lines = content.replace('\r', '').split('\n')

# Remove the first and last 2 lines of the file
# StringIO can be considered as a file stored in memory
df = pd.read_csv(StringIO("\n".join(lines[2:-2])), header=None)
Brian
fuente
1

En mi caso, el separador no era el valor predeterminado "," sino Tab.

pd.read_csv(file_name.csv, sep='\\t',lineterminator='\\r', engine='python', header='infer')

Nota: "\ t" no funcionó como lo sugieren algunas fuentes. Se requería "\\ t".

Mihai Mehe
fuente
0

Tuve un error similar y el problema era que tenía algunas comillas escapadas en mi archivo csv y necesitaba establecer el parámetro escapechar de manera adecuada.

jvvw
fuente