Erro do Python Pandas ao tokenizar dados

341

Estou tentando usar pandas para manipular um arquivo .csv, mas recebo este erro:

pandas.parser.CParserError: Erro ao tokenizar dados. Erro C: 2 campos esperados na linha 3, serra 12

Eu tentei ler os documentos dos pandas, mas não encontrei nada.

Meu código é simples:

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

Como posso resolver isto? Devo usar o csvmódulo ou outro idioma?

O arquivo é de Morningstar

abuteau
fonte
10
Se este erro surgir ao ler um arquivo gravado por pandas.to_csv(), PODE ser porque existe um '\ r' nos nomes das colunas; nesse caso, to_csv () gravará os nomes das colunas subsequentes na primeira coluna do quadro de dados, causando uma diferença entre o número de colunas nas primeiras X linhas. Essa diferença é uma causa do erro C.
usar o seguinte comando
8
Em algum momento, apenas explicitamente fornecer o parâmetro "sep" ajuda. Parece ser um problema de analisador.
Gilgamash # 23/18
2
Este erro pode ocorrer também quando você está usando vírgula como delimitador e tem mais vírgulas do que o esperado (mais campos na linha de erro e depois definidos no cabeçalho). Portanto, você precisa remover o campo adicional ou remover a vírgula extra, se houver por engano. Você pode corrigir isso manualmente e não precisará pular as linhas de erro.
tsveti_iko
2
O comentário de gilgamash me ajudou. Abra o arquivo csv em um editor de texto (como o editor do Windows ou o bloco de notas ++) para ver qual caractere é usado para a separação. Se é um ponto e vírgula, por exemplo, tente pd.read_csv("<path>", sep=";"). Não use o Excel para verificação, pois às vezes coloca os dados em colunas por padrão e, portanto, remove o separador.
Julian
Em relação ao comentário de @gilgamash - isso me enviou na direção certa, no entanto, no meu caso, foi resolvido explicitamente não fornecendo o parâmetro "sep".
TheLoneDeranger

Respostas:

514

você também pode tentar;

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

Observe que isso fará com que as linhas incorretas sejam ignoradas.

richie
fonte
152
Observe que o uso de error_bad_lines = False fará com que as linhas incorretas sejam ignoradas.
Biobirdman 20/05
10
Tropeçou nesta resposta, existe uma maneira de preencher colunas ausentes em linhas que produzem algo como expected 8 fields, saw 9?
Petra Barus
26
A melhor solução é investigar o arquivo incorreto e corrigir as linhas incorretas para que possam ser lidas read_csv. @PetraBarus, por que não adicionar colunas aos arquivos CSV que estão faltando (com valores nulos conforme necessário)?
dbliss
4
Sim, acabei de fazer isso. É muito mais fácil adicionando colunas. A abertura do CSV em uma planilha faz isso.
Petra Barus
5
Passar names=["col1", "col2", ...]para o número máximo de colunas esperadas também funciona, e foi assim que resolvi esse problema quando me deparei com ele. Veja: stackoverflow.com/questions/18039057/…
Steven Rouk
99

Pode ser um problema com

  • os delimitadores nos seus dados
  • a primeira linha, como @TomAugspurger observou

Para resolvê-lo, tente especificar os argumentos sepe / ou headerao chamar read_csv. Por exemplo,

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

No código acima, sepdefine seu delimitador e header=Noneinforma aos pandas que seus dados de origem não têm linha para títulos de cabeçalhos / colunas. Assim diz os documentos : "Se o arquivo não contiver linha de cabeçalho, você deverá passar explicitamente o cabeçalho = Nenhum". Nesse caso, os pandas criam automaticamente índices de número inteiro para cada campo {0,1,2, ...}.

De acordo com os documentos, o delimitador não deve ser um problema. Os documentos dizem que "se sep for Nenhum [não especificado], tentará determinar isso automaticamente". No entanto, não tive boa sorte com isso, incluindo instâncias com delimitadores óbvios.

grisaíte
fonte
Sim, às vezes o delimitador pode ser a causa desse problema. Eu enfrentei o mesmo problema em que delimitador era um ponto e vírgula (;)
Anurag Sharma
43

O analisador está ficando confuso com o cabeçalho do arquivo. Ele lê a primeira linha e infere o número de colunas dessa linha. Mas as duas primeiras linhas não são representativas dos dados reais no arquivo.

Experimente com data = pd.read_csv(path, skiprows=2)

TomAugspurger
fonte
30

Seu arquivo CSV pode ter um número variável de colunas e read_csvinferir o número de colunas das primeiras linhas. Duas maneiras de resolvê-lo neste caso:

1) Altere o arquivo CSV para ter uma primeira linha fictícia com número máximo de colunas (e especifique header=[0])

2) Ou use names = list(range(0,N))onde N é o número máximo de colunas.

computadorista
fonte
24

Definitivamente, esse é um problema do delimitador, já que a maioria dos CSVs CSV é criada usando, sep='/t'então tente read_csvusar o caractere de tabulação (\t)usando o separador /t. portanto, tente abrir usando a seguinte linha de código.

data=pd.read_csv("File_path", sep='\t')
Piyush S. Wanare
fonte
5
@MichaelQueue: Isso está incorreto. Um CSV, embora geralmente delimitado por vírgula, também pode ser delimitado por outros caracteres. Consulte as especificações CSV . Pode ser uma vírgula, uma guia ('\ t'), ponto-e-vírgula e possivelmente espaços adicionais. :)
DJGrandpaJ
no meu caso, era uma questão de separador. read_csv aparentemente padrões para vírgulas, e eu tenho campos de texto que incluem vírgulas (e os dados foram armazenados com um separador diferente de qualquer maneira)
user108569
Se vírgulas são usadas nos valores, mas tab é o delimitador e sep não é usado (ou como sugerido acima dos delimitadores, seja o que for que se presume que ocorra nos valores), esse erro ocorrerá. Certifique-se de que o delimitador não ocorra em nenhum dos valores; caso contrário, algumas linhas parecerão ter o número incorreto de colunas
demongolem
Estou usando o Excel 2016 ao criar o CSV e usando sep = ';' trabalhar para mim
Abdullah disse
18

Eu também tive esse problema, mas talvez por um motivo diferente. Eu tinha algumas vírgulas no CSV que estavam adicionando uma coluna adicional que os pandas estavam tentando ler. Usando o seguinte funciona, mas simplesmente ignora as linhas incorretas:

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

Se você deseja manter as linhas um tipo feio de hack para lidar com os erros, faça algo como o seguinte:

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

Comecei a escrever um script para reinserir as linhas no DataFrame, pois as linhas incorretas serão fornecidas pela variável 'line' no código acima. Tudo isso pode ser evitado usando simplesmente o leitor csv. Esperamos que os desenvolvedores de pandas possam tornar mais fácil lidar com essa situação no futuro.

Robert Geiger
fonte
14

Eu tive esse problema, onde estava tentando ler em um CSV sem passar os nomes das colunas.

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

Especifiquei os nomes das colunas em uma lista com antecedência e depois os passei para eles names, e eles foram resolvidos imediatamente. Se você não tiver definido nomes de colunas, poderá criar tantos nomes de espaços reservados quanto o número máximo de colunas que possam estar em seus dados.

col_names = ["col1", "col2", "col3", ...]
df = pd.read_csv(filename, names=col_names)
Steven Rouk
fonte
11
Esta resposta é melhor porque a linha não é excluída em comparação com se estiver usando o error_bad_line = False. Além disso, você pode facilmente descobrir quais linhas foram as problemáticas ao criar um dataframe a partir desta solução.
zipline86 27/03
Eu concordo com @ zipline86. Esta resposta é segura e inteligente.
Monica Heddneck 23/04
11

Eu já tive esse problema algumas vezes. Quase todas as vezes, o motivo é que o arquivo que eu estava tentando abrir não era um CSV salvo corretamente para começar. E por "corretamente", quero dizer que cada linha tinha o mesmo número de separadores ou colunas.

Normalmente, isso aconteceu porque eu abri o CSV no Excel e o salvei incorretamente. Embora a extensão do arquivo ainda fosse .csv, o formato CSV puro havia sido alterado.

Qualquer arquivo salvo com pandas to_csv será formatado corretamente e não deverá ter esse problema. Mas se você abrir com outro programa, isso poderá alterar a estrutura.

Espero que ajude.

elPastor
fonte
8

Me deparei com o mesmo problema. Usar pd.read_table()o mesmo arquivo de origem pareceu funcionar. Não consegui rastrear o motivo disso, mas foi uma solução útil para o meu caso. Talvez alguém com mais conhecimento possa esclarecer melhor por que funcionou.

Editar: descobri que esse erro ocorre quando você tem algum texto em seu arquivo que não possui o mesmo formato que os dados reais. Geralmente, são informações de cabeçalho ou rodapé (maiores que uma linha, portanto skip_header não funciona) que não serão separadas pelo mesmo número de vírgulas que seus dados reais (ao usar read_csv). O uso de read_table usa uma guia como delimitador, o que pode contornar o erro atual do usuário, mas apresentar outros.

Eu costumo contornar isso lendo os dados extras em um arquivo e depois usando o método read_csv ().

A solução exata pode diferir dependendo do seu arquivo real, mas essa abordagem funcionou para mim em vários casos

Legend_Ari
fonte
6

O seguinte funcionou para mim (publiquei esta resposta, porque especificamente tive esse problema em um Caderno colaborativo do Google):

df = pd.read_csv("/path/foo.csv", delimiter=';', skiprows=0, low_memory=False)
Dirk
fonte
11
Experimentei problemas quando não defini |como delimitador para o meu .csv. Prefiro tentar essa abordagem primeiro, em vez de pular linhas ou linhas ruins.
ivanleoncz 02/09/19
Eu também tive o mesmo problema, assumi que "\ t" seria detectado como delimitador por padrão. Funcionou quando defini explicitamente o delimitador como "\ t".
Rahul Jha
5

Eu tive um problema semelhante ao tentar ler uma tabela delimitada por tabulação com espaços, vírgulas e aspas:

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

Isso diz que tem algo a ver com o mecanismo de análise C (que é o padrão). Talvez mudar para um python mude qualquer coisa

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

Segmentation fault (core dumped)

Agora esse é um erro diferente.
Se seguirmos em frente e tentar remover espaços da tabela, o erro do python-engine será alterado novamente:

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

E fica claro que os pandas estavam tendo problemas para analisar nossas linhas. Para analisar uma tabela com o mecanismo python, eu precisava remover todos os espaços e aspas da tabela antes. Enquanto isso, o motor C continuava batendo mesmo com vírgulas em filas.

Para evitar a criação de um novo arquivo com substituições, fiz isso, pois minhas tabelas são pequenas:

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
Altere o mecanismo de análise, tente evitar aspas / vírgulas / espaços não delimitadores em seus dados.

lotrus28
fonte
5

O conjunto de dados que eu usei tinha muitas aspas (") estranhas à formatação. Consegui corrigir o erro incluindo este parâmetro para read_csv():

quoting=3 # 3 correlates to csv.QUOTE_NONE for pandas
user3426943
fonte
2
tropeçou exatamente na mesma coisa. Para mim, esta é a resposta correta. O aceito apenas oculta o erro.
Lhk 18/08/19
Resposta correta para mim também. +1
Taha Jirjees
4

Use delimitador no parâmetro

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

Vai ler.

Bhavesh Kumar
fonte
3

Embora não seja o caso desta pergunta, esse erro também pode aparecer com dados compactados. Definir explicitamente o valor para o kwarg compressionmeu problema foi resolvido.

result = pandas.read_csv(data_source, compression='gzip')
Programação RegularProgramada
fonte
3

Uma alternativa que eu achei útil para lidar com erros de análise semelhantes usa o módulo CSV para redirecionar dados para um pandas df. Por exemplo:

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)

Acho que o módulo CSV é um pouco mais robusto para arquivos separados por vírgula mal formatados e, portanto, obtivemos sucesso com essa rota para resolver problemas como esses.

bcoz
fonte
3

a seguinte sequência de comandos funciona (eu perco a primeira linha dos dados - sem cabeçalho = Nenhum presente -, mas pelo menos carrega):

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

A seguir NÃO 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: Erro ao tokenizar dados. Erro C: 53 campos esperados na linha 1605634, serra 54 A seguir NÃO funciona:

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

CParserError: Erro ao tokenizar dados. Erro C: 53 campos esperados na linha 1605634, serra 54

Portanto, no seu problema, você deve passar usecols=range(0, 2)

kepy97
fonte
3

Para aqueles que estão tendo problemas semelhantes com o Python 3 no SO Linux.

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

Tentar:

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

Às vezes, o problema não é como usar python, mas com os dados brutos.
Recebi esta mensagem de erro

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

Verificou-se que, na descrição da coluna, às vezes havia vírgulas. Isso significa que o arquivo CSV precisa ser limpo ou outro separador usado.

Peneiras Kims
fonte
1

Eu tinha um conjunto de dados com números de linha existentes, usei index_col:

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

Foi o que eu fiz.

sep='::' resolveu meu problema:

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

Eu tive um caso semelhante como este e definindo

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

trabalhou

Adewole Adesola
fonte
1

Eu tenho o mesmo problema quando read_csv: ParserError: Erro ao tokenizar dados. Acabei de salvar o arquivo csv antigo em um novo arquivo csv. O problema está resolvido!

Simin Zuo
fonte
1

O problema para mim foi que uma nova coluna foi anexada ao meu intraday CSV . A solução de resposta aceita não funcionaria, pois todas as linhas futuras seriam descartadas se eu usasse error_bad_lines=False.

A solução neste caso era usar os usecols parâmetro pd.read_csv(). Dessa forma, posso especificar apenas as colunas que preciso ler no CSV e meu código Python permanecerá resiliente a futuras alterações no CSV, desde que exista uma coluna de cabeçalho (e os nomes das colunas não sejam alterados).

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.

Exemplo

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

Outro benefício disso é que eu posso carregar muito menos dados na memória se estiver usando apenas 3-4 colunas de um CSV com 18 a 20 colunas.

Scott Skiles
fonte
1

Resolução simples : abra o arquivo csv no excel e salve-o com um arquivo de nome diferente do formato csv. Tente importá-lo novamente, seu problema será resolvido!

Naseer
fonte
1

Eu encontrei esse erro com aspas dispersas. Eu uso o software de mapeamento que coloca aspas nos itens de texto ao exportar arquivos delimitados por vírgula. O texto que usa aspas (por exemplo, '= pés e "= polegadas) pode ser problemático ao induzir colisões com delimitadores. Considere este exemplo que observa que uma impressão de log de poço de 5 polegadas é ruim:

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

Usar 5"como taquigrafia para 5 inchacaba jogando uma chave inglesa nas obras. O Excel simplesmente retira as aspas extras, mas o Pandas falha sem o error_bad_lines=Falseargumento mencionado acima.

Andrew Silver
fonte
1

Até onde eu sei, e depois de examinar seu arquivo, o problema é que o arquivo csv que você está tentando carregar possui várias tabelas. Existem linhas vazias ou linhas que contêm títulos de tabela. Tente dar uma olhada nesta resposta do Stackoverflow . Ele mostra como conseguir isso programaticamente.

Outra abordagem dinâmica para fazer isso seria usar o módulo csv , ler todas as linhas de cada vez e fazer verificações de sanidade / expressões regulares, para inferir se a linha é (título / cabeçalho / valores / em branco). Você tem mais uma vantagem com essa abordagem: pode dividir / acrescentar / coletar seus dados em objetos python, conforme desejado.

O mais fácil de tudo seria usar a função pandas pd.read_clipboard()após selecionar e copiar manualmente a tabela na área de transferência, caso você possa abrir o csv no excel ou algo assim.

Irrelevante :

Além disso, é irrelevante para o seu problema, mas porque ninguém mencionou isso : eu tive esse mesmo problema ao carregar alguns conjuntos de dados como o seeds_dataset.txtda UCI. No meu caso, o erro estava ocorrendo porque alguns separadores tinham mais espaços em branco do que uma guia verdadeira \t. Veja a linha 3 a seguir, por exemplo

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

Portanto, use \t+no padrão separador em vez de \t.

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

No meu caso, é porque o formato da primeira e da última duas linhas do arquivo csv é diferente do conteúdo intermediário do arquivo.

Então, o que faço é abrir o arquivo csv como uma sequência, analisar o conteúdo da sequência e usar read_csvpara obter um quadro de dados.

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
fonte
1

No meu caso, o separador não era o padrão "," mas a tab.

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

Nota: "\ t" não funcionou como sugerido por algumas fontes. "\\ t" foi necessário.

Mihai.Mehe
fonte
0

Ocorreu um erro semelhante e o problema era que eu tinha algumas aspas escapadas no meu arquivo csv e precisava definir o parâmetro escapechar adequadamente.

jvvw
fonte