Erreur de python Pandas lors de la tokenisation des données

343

J'essaie d'utiliser des pandas pour manipuler un fichier .csv mais j'obtiens cette erreur:

pandas.parser.CParserError: Erreur lors de la tokenisation des données. Erreur C: 2 champs attendus sur la ligne 3, vu 12

J'ai essayé de lire la documentation des pandas, mais je n'ai rien trouvé.

Mon code est simple:

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

Comment puis-je résoudre ça? Dois-je utiliser lecsv module ou une autre langue?

Le fichier provient de Morningstar

abuteau
la source
10
Si cette erreur survient lors de la lecture d'un fichier écrit par pandas.to_csv(), cela POURRAIT être dû au fait qu'il y a un '\ r' dans les noms de colonnes, auquel cas to_csv () écrira en fait les noms de colonnes suivants dans la première colonne du bloc de données, provoquant une différence entre le nombre de colonnes dans les X premières lignes. Cette différence est l'une des causes de l'erreur C.
user0
9
Parfois, donner simplement explicitement le paramètre "sep" aide. Semble être un problème d'analyse.
gilgamash
2
Cette erreur peut également survenir lorsque vous utilisez une virgule comme délimiteur et que vous avez plus de virgules que prévu (plus de champs dans la ligne d'erreur puis définis dans l'en-tête). Vous devez donc supprimer le champ supplémentaire ou supprimer la virgule supplémentaire s'il s'y trouve par erreur. Vous pouvez résoudre ce problème manuellement et vous n'avez pas besoin d'ignorer les lignes d'erreur.
tsveti_iko
2
Le commentaire de gilgamash m'a aidé. Ouvrez le fichier csv dans un éditeur de texte (comme l'éditeur Windows ou le bloc-notes ++) afin de voir quel caractère est utilisé pour la séparation. Si c'est un point-virgule, essayez par exemple pd.read_csv("<path>", sep=";"). N'utilisez pas Excel pour vérifier car il place parfois les données dans des colonnes par défaut et supprime donc le séparateur.
Julian
Concernant le commentaire de @gilgamash - cela m'a envoyé dans la bonne direction, mais dans mon cas, il a été résolu en ne donnant explicitement pas le paramètre "sep".
TheLoneDeranger

Réponses:

515

vous pouvez également essayer;

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

Notez que cela entraînera le saut des lignes incriminées.

Richie
la source
152
Notez que l'utilisation de error_bad_lines = False entraînera le saut des lignes incriminées.
biobirdman
10
Trébuché sur cette réponse, existe-t-il un moyen de remplir les colonnes manquantes sur les lignes qui produisent quelque chose comme expected 8 fields, saw 9?
Petra Barus du
26
La meilleure solution consiste à enquêter sur le fichier incriminé et à corriger les mauvaises lignes afin qu'elles puissent être lues par read_csv. @PetraBarus, pourquoi ne pas simplement ajouter des colonnes aux fichiers CSV qui leur manquent (avec des valeurs nulles au besoin)?
dbliss
4
Oui, je viens de le faire. C'est beaucoup plus facile en ajoutant des colonnes. Ouvrir CSV dans une feuille de calcul fait cela.
Petra Barus
5
La transmission names=["col1", "col2", ...]du nombre maximal de colonnes attendues fonctionne également, et c'est ainsi que j'ai résolu ce problème lorsque je l'ai rencontré. Voir: stackoverflow.com/questions/18039057/…
Steven Rouk
100

Cela pourrait être un problème avec

  • les délimiteurs dans vos données
  • la première ligne, comme l'a noté @TomAugspurger

Pour le résoudre, essayez de spécifier les arguments sepet / ou headerlors de l'appel read_csv. Par exemple,

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

Dans le code ci-dessus, sepdéfinit votre délimiteur et header=Noneindique aux pandas que vos données source n'ont pas de ligne pour les en-têtes / titres de colonne. Ainsi dit la documentation : "Si le fichier ne contient pas de ligne d'en-tête, alors vous devez explicitement passer header = None". Dans ce cas, pandas crée automatiquement des indices de nombres entiers pour chaque champ {0,1,2, ...}.

Selon les documents, le délimiteur ne devrait pas être un problème. Les documents disent que "si sep est Aucun [non spécifié], il essaiera de le déterminer automatiquement." Cependant, je n'ai pas eu de chance avec cela, y compris des cas avec des délimiteurs évidents.

grisaitis
la source
Oui, parfois le délimiteur peut être la cause de ce problème. J'ai fait face au même problème où le délimiteur était un point-virgule (;)
Anurag Sharma
43

L'analyseur devient confus par l'en-tête du fichier. Il lit la première ligne et déduit le nombre de colonnes de cette ligne. Mais les deux premières lignes ne sont pas représentatives des données réelles du fichier.

Essayez-le avec data = pd.read_csv(path, skiprows=2)

TomAugspurger
la source
30

Votre fichier CSV peut avoir un nombre variable de colonnes et read_csvdéduire le nombre de colonnes à partir des premières lignes. Deux façons de le résoudre dans ce cas:

1) Modifiez le fichier CSV pour avoir une première ligne factice avec un nombre maximum de colonnes (et spécifiez header=[0] )

2) Ou utilisez names = list(range(0,N))où N est le nombre maximum de colonnes.

informaticien
la source
25

C'est certainement un problème de délimiteur, car la plupart des CSV CSV sont créés en utilisant sep='/t'donc essayez d' read_csvutiliser le caractère de tabulation en (\t)utilisant le séparateur /t. essayez donc d'ouvrir en utilisant la ligne de code suivante.

data=pd.read_csv("File_path", sep='\t')
Piyush S. Wanare
la source
5
@MichaelQueue: C'est incorrect. Un CSV, bien que généralement délimité par une virgule, peut également être délimité par d'autres caractères. Voir les spécifications CSV . Il peut s'agir d'une virgule, d'une tabulation ('\ t'), d'un point-virgule et éventuellement d'espaces supplémentaires. :)
DJGrandpaJ
dans mon cas, c'était un problème de séparation. read_csv est apparemment par défaut des virgules, et j'ai des champs de texte qui incluent des virgules (et les données ont quand même été stockées avec un séparateur différent)
user108569
Si des virgules sont utilisées dans les valeurs mais tab est le délimiteur et sep n'est pas utilisé (ou comme suggéré ci-dessus, les délimiteurs, quoi qu'il soit supposé se produire dans les valeurs), cette erreur se produira. Assurez-vous que le délimiteur n'apparaît dans aucune des valeurs, sinon certaines lignes
sembleront
J'utilise Excel 2016 lors de la création du CSV et en utilisant sep = ';' travailler pour moi
Abdullah Said
18

J'ai également eu ce problème, mais peut-être pour une raison différente. J'avais des virgules de fin dans mon CSV qui ajoutaient une colonne supplémentaire que les pandas tentaient de lire. En utilisant les travaux suivants, mais il ignore simplement les mauvaises lignes:

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

Si vous voulez garder les lignes un hack laid pour gérer les erreurs, faites quelque chose comme ceci:

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

J'ai procédé à l'écriture d'un script pour réinsérer les lignes dans le DataFrame car les mauvaises lignes seront données par la variable 'line' dans le code ci-dessus. Tout cela peut être évité en utilisant simplement le lecteur csv. Espérons que les développeurs de pandas pourront faciliter la gestion de cette situation à l'avenir.

Robert Geiger
la source
14

J'ai eu ce problème, où j'essayais de lire dans un CSV sans passer de noms de colonnes.

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

J'ai spécifié les noms de colonne dans une liste au préalable, puis je les ai passés dans names, et il l'a résolu immédiatement. Si vous n'avez pas défini de noms de colonne, vous pouvez simplement créer autant de noms d'espace réservé que le nombre maximal de colonnes qui peuvent se trouver dans vos données.

col_names = ["col1", "col2", "col3", ...]
df = pd.read_csv(filename, names=col_names)
Steven Rouk
la source
1
Cette réponse est meilleure car la ligne n'est pas supprimée par rapport à l'utilisation de error_bad_line = False. De plus, vous pouvez facilement déterminer quelles lignes étaient les lignes à problème une fois que vous avez créé une trame de données à partir de cette solution.
zipline86
Je suis d'accord avec @ zipline86. Cette réponse est sûre et intelligente.
Monica Heddneck
11

J'ai moi-même eu ce problème plusieurs fois. Presque à chaque fois, la raison en est que le fichier que j'essayais d'ouvrir n'était pas un CSV correctement enregistré pour commencer. Et par "correctement", je veux dire que chaque ligne avait le même nombre de séparateurs ou de colonnes.

En général, cela s'est produit parce que j'avais ouvert le CSV dans Excel, puis que je l'avais mal enregistré. Même si l'extension de fichier était toujours .csv, le format CSV pur avait été modifié.

Tout fichier enregistré avec pandas to_csv sera correctement formaté et ne devrait pas avoir ce problème. Mais si vous l'ouvrez avec un autre programme, cela peut changer la structure.

J'espère que cela pourra aider.

elPastor
la source
8

Je suis tombé sur le même problème. L'utilisation pd.read_table()sur le même fichier source semble fonctionner. Je n'ai pas pu en trouver la raison, mais c'était une solution de contournement utile pour mon cas. Peut-être que quelqu'un de plus compétent peut éclairer pourquoi cela a fonctionné.

Edit: J'ai trouvé que cette erreur se glisse lorsque vous avez du texte dans votre fichier qui n'a pas le même format que les données réelles. Il s'agit généralement d'informations d'en-tête ou de pied de page (supérieures à une ligne, donc skip_header ne fonctionne pas) qui ne seront pas séparées par le même nombre de virgules que vos données réelles (lors de l'utilisation de read_csv). L'utilisation de read_table utilise un onglet comme délimiteur qui pourrait contourner l'erreur actuelle des utilisateurs mais en introduire d'autres.

Je contourne généralement cela en lisant les données supplémentaires dans un fichier, puis en utilisant la méthode read_csv ().

La solution exacte peut différer en fonction de votre fichier réel, mais cette approche a fonctionné pour moi dans plusieurs cas

Legend_Ari
la source
6

Les éléments suivants ont fonctionné pour moi (j'ai publié cette réponse, car j'avais spécifiquement ce problème dans un bloc-notes Google Colaboratory):

df = pd.read_csv("/path/foo.csv", delimiter=';', skiprows=0, low_memory=False)
Poignard
la source
1
J'ai rencontré des problèmes en ne définissant pas |le délimiteur pour mon .csv. Je préfère essayer cette approche d'abord, au lieu de sauter des lignes ou de mauvaises lignes.
ivanleoncz
J'ai également eu le même problème, j'ai supposé que "\ t" serait détecté comme délimiteur par défaut. Cela a fonctionné lorsque j'ai défini explicitement le délimiteur sur "\ t".
Rahul Jha
5

J'ai rencontré un problème similaire en essayant de lire un tableau délimité par des tabulations avec des espaces, des virgules et des guillemets:

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

Cela indique qu'il a quelque chose à voir avec le moteur d'analyse C (qui est celui par défaut). Peut-être que changer en python changera quoi que ce soit

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

Segmentation fault (core dumped)

Maintenant, c'est une erreur différente.
Si nous continuons et essayons de supprimer des espaces de la table, l'erreur du moteur python change à nouveau:

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 '"'

Et il devient clair que les pandas avaient des problèmes pour analyser nos lignes. Pour analyser une table avec le moteur python, j'avais besoin de supprimer tous les espaces et les guillemets de la table au préalable. Pendant ce temps, le moteur C continuait de planter même avec des virgules en rangées.

Pour éviter de créer un nouveau fichier avec des remplacements, je l'ai fait, car mes tables sont petites:

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
Changez le moteur d'analyse, essayez d'éviter toute citation / virgule / espace non délimitant dans vos données.

lotrus28
la source
5

Le jeu de données que j'ai utilisé avait beaucoup de guillemets (") utilisés étrangers au formatage. J'ai pu corriger l'erreur en incluant ce paramètre pour read_csv():

quoting=3 # 3 correlates to csv.QUOTE_NONE for pandas
user3426943
la source
2
tombé sur la même chose. En ce qui me concerne, c'est la bonne réponse. Celui qui est accepté cache simplement l'erreur.
lhk
Bonne réponse pour moi aussi. +1
Taha Jirjees
4

Utiliser un délimiteur dans le paramètre

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

Il va lire.

Bhavesh Kumar
la source
3

Bien que ce ne soit pas le cas pour cette question, cette erreur peut également apparaître avec des données compressées. Définir explicitement la valeur pour kwarg compressionrésoudre mon problème.

result = pandas.read_csv(data_source, compression='gzip')
Programmation régulière
la source
3

Une alternative que j'ai trouvée utile pour traiter des erreurs d'analyse similaires utilise le module CSV pour réacheminer les données vers un pandas df. Par exemple:

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)

Je trouve que le module CSV est un peu plus robuste pour les fichiers séparés par des virgules mal formatés et j'ai donc réussi avec cet itinéraire à résoudre des problèmes comme ceux-ci.

bcoz
la source
3

la séquence de commandes suivante fonctionne (je perds la première ligne des données -aucun en-tête = aucun présent-, mais au moins il se charge):

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']

Ce qui suit ne fonctionne PAS:

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: Erreur lors de la tokenisation des données. Erreur C: 53 champs attendus dans la ligne 1605634, vu 54 suivants ne fonctionnent pas:

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

CParserError: Erreur lors de la tokenisation des données. Erreur C: 53 champs attendus dans la ligne 1605634, 54

Par conséquent, dans votre problème, vous devez passer usecols=range(0, 2)

kepy97
la source
3

Pour ceux qui ont un problème similaire avec Python 3 sur Linux OS.

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

Essayer:

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

Parfois, le problème n'est pas de savoir comment utiliser python, mais avec les données brutes.
J'ai ce message d'erreur

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

Il s'est avéré que dans la description de la colonne, il y avait parfois des virgules. Cela signifie que le fichier CSV doit être nettoyé ou qu'un autre séparateur doit être utilisé.

Kims Sifers
la source
1

J'avais un ensemble de données avec des numéros de ligne préexistants, j'ai utilisé index_col:

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

C'est ce que j'ai fait.

sep='::' résolu mon problème:

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

J'ai eu un cas similaire à celui-ci et le réglage

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

travaillé

Adewole Adesola
la source
1

J'ai le même problème lorsque read_csv: ParserError: erreur lors de la tokenisation des données. Je viens de sauvegarder l'ancien fichier csv dans un nouveau fichier csv. Le problème est résolu!

Simin Zuo
la source
1

Le problème pour moi était qu'une nouvelle colonne était ajoutée à mon CSV intraday . La solution de réponse acceptée ne fonctionnerait pas car chaque ligne future serait rejetée si j'utilisais error_bad_lines=False.

La solution dans ce cas était d'utiliser le paramètre usecols dans pd.read_csv(). De cette façon, je peux spécifier uniquement les colonnes que je dois lire dans le CSV et mon code Python restera résistant aux futures modifications CSV tant qu'une colonne d'en-tête existe (et que les noms des colonnes ne changent pas).

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.

Exemple

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

Un autre avantage de ceci est que je peux charger beaucoup moins de données en mémoire si j'utilise seulement 3-4 colonnes d'un CSV qui a 18-20 colonnes.

Scott Skiles
la source
1

Résolution simple : ouvrez le fichier csv dans Excel et enregistrez-le avec un fichier de nom différent au format csv. Essayez à nouveau de l'importer spyder, votre problème sera résolu!

Naseer
la source
1

J'ai rencontré cette erreur avec un guillemet errant. J'utilise un logiciel de cartographie qui mettra des guillemets autour des éléments de texte lors de l'exportation de fichiers délimités par des virgules. Le texte qui utilise des guillemets (par exemple '= pieds et "= pouces) peut être problématique lorsqu'il induit alors des collisions de délimiteur. Prenons cet exemple qui note qu'une impression de journal de puits de 5 pouces est mauvaise:

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

Utiliser 5"comme raccourci pour 5 inchfinir par jeter une clé dans les travaux. Excel supprimera simplement le guillemet supplémentaire, mais Pandas tombe en panne sans l' error_bad_lines=Falseargument mentionné ci-dessus.

Andrew Silver
la source
1

Autant que je sache, et après avoir jeté un œil à votre fichier, le problème est que le fichier csv que vous essayez de charger a plusieurs tables. Il existe des lignes vides ou des lignes contenant des titres de table. Essayez de jeter un œil à cette réponse Stackoverflow . Il montre comment y parvenir par programme.

Une autre approche dynamique pour ce faire serait d’utiliser le module csv , de lire chaque ligne à la fois et de faire des vérifications d'intégrité / des expressions régulières, pour déduire si la ligne est (titre / en-tête / valeurs / vide). Vous avez un avantage supplémentaire avec cette approche, que vous pouvez diviser / ajouter / collecter vos données en objets python comme vous le souhaitez.

Le plus simple serait d'utiliser la fonction pandas pd.read_clipboard() après avoir sélectionné et copié manuellement la table dans le presse-papiers, au cas où vous pourriez ouvrir le csv dans excel ou quelque chose.

Hors du sujet :

De plus, sans rapport avec votre problème, mais parce que personne n'en a fait mention : j'ai eu ce même problème lors du chargement de certains ensembles de données, tels que ceux seeds_dataset.txtde l'UCI. Dans mon cas, l'erreur se produisait car certains séparateurs avaient plus d'espaces blancs qu'un véritable onglet \t. Voir la ligne 3 dans l'exemple suivant par exemple

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

Par conséquent, utilisez-le \t+dans le modèle de séparateur au lieu de \t.

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

Dans mon cas, c'est parce que le format des deux premières et dernières lignes du fichier csv est différent du contenu intermédiaire du fichier.

Donc, ce que je fais est d'ouvrir le fichier csv sous forme de chaîne, d'analyser le contenu de la chaîne, puis d'utiliser read_csvpour obtenir une trame de données.

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
la source
1

Dans mon cas, le séparateur n'était pas le "," par défaut mais Tab.

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

Remarque: "\ t" n'a pas fonctionné comme suggéré par certaines sources. "\\ t" était requis.

Mihai.Mehe
la source
0

J'ai eu une erreur similaire et le problème était que j'avais des guillemets d'échappement dans mon fichier csv et que je devais définir le paramètre escapechar de manière appropriée.

jvvw
la source