Python Pandas Błąd tokenizacji danych


343

Próbuję użyć pand do manipulowania plikiem .csv, ale otrzymuję ten błąd:

pandas.parser.CParserError: Błąd tokenizacji danych. Błąd C: Oczekiwano 2 pól w linii 3, patrz 12

Próbowałem czytać dokumenty pand, ale nic nie znalazłem.

Mój kod jest prosty:

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

Jak mogę to rozwiązać? Czy powinienem użyć csvmodułu lub innego języka?

Plik pochodzi od Morningstar


10
Jeśli błąd ten pojawia się podczas odczytu pliku zapisanego przez pandas.to_csv(), MUSI to być spowodowane tym, że w nazwach kolumn znajduje się „\ r”, w którym to przypadku to_csv () faktycznie zapisze nazwy kolejnych kolumn w pierwszej kolumnie ramki danych, powodując różnica między liczbą kolumn w pierwszych X wierszach. Ta różnica jest jedną z przyczyn błędu C.
użytkownik0

9
Czasami pomaga po prostu podanie parametru „sep”. Wygląda na problem z analizatorem składni.
gilgamash

2
Ten błąd może pojawić się również, gdy używasz przecinka jako separatora i masz więcej przecinków niż oczekiwano (więcej pól w wierszu błędu, a następnie zdefiniowanych w nagłówku). Musisz więc usunąć dodatkowe pole lub usunąć przecinek, jeśli jest przez pomyłkę. Możesz to naprawić ręcznie, a następnie nie musisz pomijać linii błędów.
tsveti_iko

2
Komentarz od gilgamash pomógł mi. Otwórz plik csv w edytorze tekstu (takim jak edytor systemu Windows lub notatnik ++), aby zobaczyć, który znak jest używany do separacji. Jeśli jest to średnik, np pd.read_csv("<path>", sep=";"). Spróbuj . Nie używaj programu Excel do sprawdzania, ponieważ czasami domyślnie umieszcza dane w kolumnach, a zatem usuwa separator.
Julian

Jeśli chodzi o komentarz przez @gilgamash - ten wysłał mnie we właściwym kierunku, jednak w moim przypadku został rozwiązany przez wyraźnie nie podając parametr „SEP”.
TheLoneDeranger,

Odpowiedzi:


515

możesz także spróbować;

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

Pamiętaj, że spowoduje to pominięcie linii naruszających.


152
Zauważ, że użycie error_bad_lines = False spowoduje, że błędne linie zostaną pominięte.
biobirdman

10
Natknąłem się na tę odpowiedź, czy istnieje sposób na uzupełnienie brakujących kolumn w wierszach, które generują coś podobnego expected 8 fields, saw 9?
Petra Barus

26
Lepszym rozwiązaniem jest zbadanie niepoprawnego pliku i poprawienie złych linii, aby można je było odczytać read_csv. @PetraBarus, dlaczego po prostu nie dodać kolumn do plików CSV, w których ich brakuje (z wartościami null w razie potrzeby)?
dbliss

4
Tak, właśnie to zrobiłem. O wiele łatwiej jest dodawać kolumny. Robi to otwarcie CSV w arkuszu kalkulacyjnym.
Petra Barus

5
Przekazywanie names=["col1", "col2", ...]maksymalnej liczby oczekiwanych kolumn również działa i w ten sposób rozwiązałem ten problem, gdy go spotkałem. Zobacz: stackoverflow.com/questions/18039057/...
Steven Rouk

100

Może to być problem z

  • ograniczniki w twoich danych
  • pierwszy rząd, jak zauważył @TomAugspurger

Aby go rozwiązać, spróbuj podać argumenty sepi / lub headerargumenty podczas wywoływania read_csv. Na przykład,

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

W powyższym kodzie sepdefiniuje ogranicznik i header=Nonemówi pandom, że dane źródłowe nie mają wiersza dla nagłówków / tytułów kolumn. Tak mówi dokument : „Jeśli plik nie zawiera wiersza nagłówka, należy jawnie przekazać nagłówek = Brak”. W tym przypadku pandy automatycznie tworzą wskaźniki liczb całkowitych dla każdego pola {0,1,2, ...}.

Według doktryn, separator nie powinien stanowić problemu. Dokumenty mówią, że „jeśli sep to None [nie określono], spróbuje to automatycznie ustalić”. Jednak nie miałem z tym szczęścia, w tym przypadków z oczywistymi ogranicznikami.


Tak, czasem separator może być przyczyną tego problemu. Napotkałem ten sam problem, w którym separatorem był średnik (;)
Anurag Sharma

43

Parser jest mylony przez nagłówek pliku. Odczytuje pierwszy wiersz i podaje liczbę kolumn z tego wiersza. Ale dwa pierwsze wiersze nie reprezentują rzeczywistych danych w pliku.

Wypróbuj z data = pd.read_csv(path, skiprows=2)


30

Twój plik CSV może mieć zmienną liczbę kolumn i read_csvwywnioskować liczbę kolumn z kilku pierwszych wierszy. Dwa sposoby rozwiązania tego problemu w tym przypadku:

1) Zmień plik CSV, tak aby zawierał fikcyjny pierwszy wiersz z maksymalną liczbą kolumn (i określ header=[0])

2) Lub użyj names = list(range(0,N))gdzie N jest maksymalną liczbą kolumn.


25

Jest to z pewnością kwestia ogranicznika, ponieważ większość plików CSV CSV jest utworzonych przy użyciu, sep='/t'więc spróbuj read_csvużyć znaku tabulacji (\t)za pomocą separatora /t. więc spróbuj otworzyć, używając następującej linii kodu.

data=pd.read_csv("File_path", sep='\t')

5
@MichaelQueue: To jest niepoprawne. Plik CSV, choć często rozdzielany przecinkiem, może być również rozdzielany innymi znakami. Zobacz specyfikacje CSV . Może to być przecinek, tabulator („\ t”), średnik i ewentualnie dodatkowe spacje. :)
DJGrandpaJ

w moim przypadku była to kwestia separatora. read_csv najwyraźniej domyślnie ma przecinki, a ja mam pola tekstowe zawierające przecinki (a dane i tak były przechowywane z innym separatorem)
użytkownik108569

Jeśli w wartościach używane są przecinki, ale tab jest separatorem, a sep nie jest używany (lub jak sugerowano powyżej w ogranicznikach, niezależnie od tego, co, jak się zakłada, występuje w wartościach), wówczas wystąpi ten błąd. Upewnij się, że separator nie występuje w żadnej z wartości, w przeciwnym razie niektóre wiersze będą miały niepoprawną liczbę kolumn
demongolem

Korzystam z programu Excel 2016 podczas tworzenia pliku CSV i używam sep = ';' pracujcie dla mnie
Abdullah powiedział

18

Miałem również ten problem, ale może z innego powodu. W CSV miałem kilka przecinków końcowych, które dodawały dodatkową kolumnę, którą pandy próbowały odczytać. Korzystanie z poniższych działa, ale po prostu ignoruje złe linie:

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

Jeśli chcesz, aby linie były brzydkim hackem do obsługi błędów, wykonaj następujące czynności:

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

Zacząłem pisać skrypt, aby ponownie wstawić linie do DataFrame, ponieważ złe linie zostaną podane przez zmienną „line” w powyższym kodzie. Można tego wszystkiego uniknąć, po prostu używając czytnika csv. Mamy nadzieję, że twórcy pand ułatwią radzenie sobie z tą sytuacją w przyszłości.


14

Miałem ten problem, gdy próbowałem czytać w CSV bez podawania nazw kolumn.

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

Wcześniej określiłem nazwy kolumn na liście, a następnie przekazałem je namesi rozwiązało to natychmiast. Jeśli nie masz ustawionych nazw kolumn, możesz po prostu utworzyć tyle nazw symboli zastępczych, ile maksymalna liczba kolumn może znajdować się w danych.

col_names = ["col1", "col2", "col3", ...]
df = pd.read_csv(filename, names=col_names)

1
Ta odpowiedź jest lepsza, ponieważ wiersz nie zostanie usunięty w porównaniu z tym, jeśli używasz error_bad_line = False. Dodatkowo możesz łatwo zorientować się, które linie były problematyczne po utworzeniu ramki danych z tego rozwiązania.
zipline86

Zgadzam się z @ zipline86. Ta odpowiedź jest bezpieczna i inteligentna.
Monica Heddneck

11

Sam miałem ten problem kilka razy. Niemal za każdym razem powodem jest to, że plik, który próbowałem otworzyć, nie był poprawnie zapisanym plikiem CSV. Przez „prawidłowo” rozumiem, że każdy wiersz miał taką samą liczbę separatorów lub kolumn.

Zwykle dzieje się tak, ponieważ otworzyłem plik CSV w programie Excel, a następnie zapisałem go nieprawidłowo. Mimo że rozszerzenie pliku nadal było w formacie .csv, czysty format CSV został zmieniony.

Każdy plik zapisany z pandami to_csv zostanie poprawnie sformatowany i nie powinien mieć tego problemu. Ale jeśli otworzysz go za pomocą innego programu, może to zmienić strukturę.

Mam nadzieję, że to pomaga.


8

Natknąłem się na ten sam problem. pd.read_table()Wydawało się, że używanie tego samego pliku źródłowego działa. Nie mogłem wyśledzić przyczyny tego, ale było to przydatne obejście w mojej sprawie. Być może ktoś bardziej kompetentny może rzucić więcej światła na to, dlaczego to zadziałało.

Edycja: Odkryłem, że ten błąd pojawia się, gdy w pliku jest tekst, który nie ma tego samego formatu co rzeczywiste dane. Zazwyczaj są to informacje nagłówka lub stopki (więcej niż jeden wiersz, więc skip_header nie działa), które nie będą oddzielone taką samą liczbą przecinków, jak rzeczywiste dane (przy użyciu read_csv). Korzystanie z read_table wykorzystuje tabulator jako ogranicznik, który może ominąć bieżący błąd użytkowników, ale wprowadzić inne.

Zwykle omijam ten problem, czytając dodatkowe dane do pliku, a następnie używam metody read_csv ().

Dokładne rozwiązanie może się różnić w zależności od twojego rzeczywistego pliku, ale to podejście zadziałało dla mnie w kilku przypadkach


6

Poniższe działało dla mnie (opublikowałem tę odpowiedź, ponieważ miałem konkretnie ten problem w Notatniku Google Colaboratory):

df = pd.read_csv("/path/foo.csv", delimiter=';', skiprows=0, low_memory=False)

1
Eksperymentowałem z problemami, gdy nie ustawiałem |jako ogranicznika dla mojego pliku .csv. Wolę najpierw wypróbować to podejście, zamiast pomijania linii lub złych linii.
ivanleoncz

Miałem również ten sam problem, zakładałem, że domyślnie „\ t” zostanie wykryty jako separator. Działa, gdy jawnie ustawiam ogranicznik na „\ t”.
Rahul Jha,

5

Miałem podobny problem podczas próby odczytania tabeli rozdzielanej tabulatorami ze spacjami, przecinkami i cudzysłowami:

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

To mówi, że ma to coś wspólnego z silnikiem parsującym C (który jest domyślny). Może zmiana na python zmieni wszystko

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

Segmentation fault (core dumped)

To inny błąd.
Jeśli pójdziemy dalej i spróbujemy usunąć spacje z tabeli, błąd z silnika Python ponownie się zmieni:

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

I staje się jasne, że pandy miały problemy z analizą naszych wierszy. Aby przeanalizować tabelę za pomocą silnika Python, musiałem wcześniej usunąć wszystkie spacje i cytaty z tabeli. Tymczasem silnik C ciągle się zawieszał, nawet z przecinkami w rzędach.

Aby uniknąć tworzenia nowego pliku z zamiennikami, zrobiłem to, ponieważ moje tabele są małe:

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
Zmień silnik parsowania, staraj się unikać cudzysłowów / przecinków / spacji w danych.


5

Zestaw danych, którego użyłem, zawierał wiele cudzysłowów („) używanych poza formatowaniem. Byłem w stanie naprawić błąd, włączając ten parametr dla read_csv():

quoting=3 # 3 correlates to csv.QUOTE_NONE for pandas

2
natknąłem się na dokładnie to samo. Jeśli chodzi o mnie, to jest poprawna odpowiedź. Ten zaakceptowany po prostu ukrywa błąd.
lhk 18.08.19

Również dla mnie poprawna odpowiedź. +1
Taha Jirjees

4

Użyj separatora w parametrze

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

Przeczytam.


3

Chociaż nie jest tak w przypadku tego pytania, błąd ten może również pojawić się w przypadku skompresowanych danych. Jawne ustawienie wartości dla kwarg compressionrozwiązania mojego problemu.

result = pandas.read_csv(data_source, compression='gzip')

3

Alternatywą, która okazała się przydatna w radzeniu sobie z podobnymi błędami analizy, jest użycie modułu CSV do przekierowania danych do pandy df. Na przykład:

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)

Uważam, że moduł CSV jest nieco bardziej odporny na źle sformatowane pliki oddzielone przecinkami, dlatego odniosłem sukces dzięki tej ścieżce rozwiązania takich problemów.


3

działa następująca sekwencja poleceń (tracę pierwszy wiersz danych -no header = None present-, ale przynajmniej ładuje):

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

Następujące NIE działa:

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: Błąd tokenizacji danych. Błąd C: Oczekiwano 53 pól w linii 1605634, piła 54 Następujące NIE działa:

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

CParserError: Błąd tokenizacji danych. Błąd C: Oczekiwano 53 pól w linii 1605634, piła 54

Dlatego w swoim problemie musisz przejść usecols=range(0, 2)


3

Dla tych, którzy mają podobny problem z Python 3 w systemie Linux.

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

Próbować:

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

2

Czasami problemem nie jest użycie Pythona, ale surowe dane.
Mam ten komunikat o błędzie

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

Okazało się, że w opisie kolumny czasem znajdowały się przecinki. Oznacza to, że plik CSV musi zostać wyczyszczony lub należy użyć innego separatora.



1

Miałem zestaw danych z wcześniej istniejącymi numerami wierszy, użyłem index_col:

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

1

Oto co zrobiłem.

sep='::' rozwiązałem mój problem:

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

1

Miałem podobny przypadek jak ten i ustawienie

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

pracował


1

Mam ten sam problem, gdy read_csv: ParserError: Błąd tokenizacji danych. Właśnie zapisałem stary plik csv w nowym pliku csv. Problem jest rozwiązany!


1

Problemem było to, że do mojego CSV dołączono nową kolumnę w ciągu dnia . Akceptowane rozwiązanie odpowiedzi nie działałoby, ponieważ każdy przyszły wiersz zostałby odrzucony, gdybym go użył error_bad_lines=False.

Rozwiązaniem w tym przypadku było użycie parametru usecols w pd.read_csv(). W ten sposób mogę określić tylko kolumny, które muszę wczytać do pliku CSV, a mój kod Python pozostanie odporny na przyszłe zmiany CSV, o ile istnieje kolumna nagłówka (a nazwy kolumn nie zmieniają się).

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.

Przykład

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

Inną zaletą tego jest to, że mogę załadować znacznie mniej danych do pamięci, jeśli używam tylko 3-4 kolumn CSV, który ma 18-20 kolumn.


1

Prosta rozdzielczość : otwórz plik csv w programie Excel i zapisz go pod innym plikiem w formacie csv. Ponownie spróbuj zaimportować go pająk, Twój problem zostanie rozwiązany!


1

Napotkałem ten błąd ze zbłąkanym cudzysłowem. Używam oprogramowania do mapowania, które umieszcza cudzysłowy wokół elementów tekstowych podczas eksportowania plików rozdzielanych przecinkami. Tekst wykorzystujący znaki cudzysłowu (np. „= Stopy i” = cale) może być problematyczny, gdy wywoła kolizję ogranicznika. Rozważ ten przykład, w którym zauważono, że 5-calowy wydruk dziennika zagłębienia jest zły:

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

Używanie 5"jako skrótu dla 5 inchkończy się rzuceniem klucza w pracach. Excel po prostu usunie dodatkowy znak cudzysłowu, ale Panda rozpadnie się bez powyższego error_bad_lines=Falseargumentu.


1

O ile wiem, po obejrzeniu pliku problem polega na tym, że plik csv, który próbujesz załadować, ma wiele tabel. Istnieją puste wiersze lub wiersze zawierające tytuły tabel. Spróbuj spojrzeć na tę odpowiedź Stackoverflow . Pokazuje, jak to osiągnąć programowo.

Innym dynamicznym podejściem do tego byłoby użycie modułu csv , odczytywanie każdego wiersza na raz i sprawdzanie poprawności / wyrażeń regularnych, aby wywnioskować, czy wiersz jest (tytuł / nagłówek / wartości / puste miejsce). Masz jeszcze jedną zaletę dzięki temu podejściu, że możesz dzielić / dołączać / zbierać dane w obiektach python zgodnie z potrzebami.

Najprościej byłoby użyć funkcji pandy pd.read_clipboard()po ręcznym wybraniu i skopiowaniu tabeli do schowka, na wypadek gdybyś mógł otworzyć plik CSV w programie Excel lub coś takiego.

Nieistotne :

Ponadto nie ma znaczenia dla twojego problemu, ale ponieważ nikt o tym nie wspomniał : miałem ten sam problem podczas ładowania niektórych zestawów danych, takich jak seeds_dataset.txtz UCI. W moim przypadku błąd występował, ponieważ niektóre separatory miały więcej białych znaków niż prawdziwa karta \t. Zobacz na przykład wiersz 3 poniżej

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

Dlatego należy użyć \t+wzorca separatora zamiast \t.

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

1

W moim przypadku dzieje się tak, ponieważ format pierwszych i ostatnich dwóch wierszy pliku csv różni się od środkowej zawartości pliku.

Więc to, co robię, to otwieram plik csv jako ciąg, analizuję zawartość ciągu, a następnie używam, read_csvaby uzyskać ramkę danych.

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)

1

W moim przypadku separator nie był domyślnym „”, ale Tab.

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

Uwaga: „\ t” nie działało, jak sugerują niektóre źródła. „\\ t” było wymagane.


0

Miałem podobny błąd, a problem polegał na tym, że w pliku csv miałem cudzysłowy i potrzebowałem odpowiednio ustawić parametr escapechar.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.