574 Stimmen

Pandas read_csv: low_memory und dtype Optionen

df = pd.read_csv('somefile.csv')

...gibt einen Fehler:

.../site-packages/pandas/io/parsers.py:1130: DtypeWarning: Spalten (4,5,7,16) haben gemischte Typen. Geben Sie die dtype-Option beim Import an oder setzen Sie low_memory=False.

Warum steht die dtype-Option in Verbindung mit low_memory, und warum könnte low_memory=False helfen?

7voto

Rajat Saxena Punkte 103

Es hat für mich funktioniert mit low_memory = False während dem Importieren eines DataFrame. Das war die einzige Änderung, die für mich funktioniert hat:

df = pd.read_csv('export4_16.csv',low_memory=False)

7voto

wfolkerts Punkte 83

Ich hatte ein ähnliches Problem beim Verarbeiten einer riesigen CSV-Datei (6 Millionen Zeilen). Ich hatte drei Probleme:

  1. die Datei enthielt seltsame Zeichen (behoben durch Codierung)
  2. der Datentyp war nicht angegeben (beheben durch Verwendung der dtype-Eigenschaft)
  3. Selbst nach der obigen Lösung hatte ich immer noch ein Problem, das mit dem file_format zusammenhing, das nicht anhand des Dateinamens definiert werden konnte (beheben durch try .. except ..)

    df = pd.read_csv(csv_file,sep=';', encoding = 'ISO-8859-1',
                     names=['permission','owner_name','group_name','size','ctime','mtime','atime','filename','full_filename'],
                     dtype={'permission':str,'owner_name':str,'group_name':str,'size':str,'ctime':object,'mtime':object,'atime':object,'filename':str,'full_filename':str,'first_date':object,'last_date':object})
    
    try:
        df['file_format'] = [Path(f).suffix[1:] for f in df.filename.tolist()]
    except:
        df['file_format'] = ''

7voto

technomage Punkte 9525

Manchmal, wenn alle Stricke reißen, möchten Sie den Pandas einfach sagen, dass sie darüber schweigen sollen:

# Ignoriere DtypeWarnings von pandas' read_csv                                                                                                                                                                                            
warnings.filterwarnings('ignore', message="^Columns.*")

6voto

Mahmoud Ragab Punkte 91

Wie der Fehler besagt, sollten Sie die Datentypen angeben, wenn Sie die read_csv()-Methode verwenden. Daher sollten Sie Folgendes schreiben:

file = pd.read_csv('example.csv', dtype='unicode')

5voto

Richard DiSalvo Punkte 850

Laut der Pandas-Dokumentation ist die Angabe von low_memory=False so lange wie engine='c' (was der Standardwert ist) eine vernünftige Lösung für dieses Problem.

Wenn low_memory=False ist, werden zunächst ganze Spalten eingelesen und dann die entsprechenden Typen bestimmt. Zum Beispiel wird die Spalte als Objekte (Strings) beibehalten, um Informationen zu erhalten.

Wenn low_memory=True (der Standardwert) ist, liest Pandas die Daten in Teilen von Zeilen ein und fügt sie dann zusammen. Dann könnten einige der Spalten wie gemischte Abschnitte von Ganzzahlen und Strings aussehen, je nachdem, ob Pandas während des Teils auf etwas gestoßen ist, das nicht in eine Ganzzahl umgewandelt werden konnte (sagen wir). Dies könnte später Probleme verursachen. Die Warnung gibt an, dass dies mindestens einmal beim Einlesen aufgetreten ist, daher sollten Sie vorsichtig sein. Die Einstellung von low_memory=False verbraucht mehr Speicher, umgeht jedoch das Problem.

Persönlich denke ich, dass low_memory=True ein schlechter Standardwert ist, aber ich arbeite in einem Bereich, der viele kleine Datensätze anstelle von großen verwendet, daher ist die Bequemlichkeit wichtiger als die Effizienz.

Der folgende Code veranschaulicht ein Beispiel, bei dem low_memory=True gesetzt ist und eine Spalte mit gemischten Typen hereinkommt. Es baut auf der Antwort von @firelynx auf

import pandas as pd
try:
    from StringIO import StringIO
except ImportError:
    from io import StringIO

# Erstelle eine große CSV-Datendatei, basierend auf dem früheren Ansatz von @firelynx
csvdata = """1,Alice
2,Bob
3,Caesar
"""

# Wir müssen die Spalte "Integer-Spalte" user_id viele Male reproduzieren, um
# pd.read_csv dazu zu bringen, tatsächlich in Teilen zu lesen. Andernfalls liest es einfach
# alles in einem Teil ein, weil es schneller ist, und wir bekommen kein "gemischter Typ"-Problem.
# Die 100000 unten wurde durch Experimente gewählt.
csvdatafull = ""
for i in range(100000):
    csvdatafull = csvdatafull + csvdata
csvdatafull =  csvdatafull + "foobar,Cthlulu\n"
csvdatafull = "user_id,username\n" + csvdatafull

sio = StringIO(csvdatafull)
# die folgende Zeile gibt mir die Warnung:
    # C:\Users\rdisa\anaconda3\lib\site-packages\IPython\core\interactiveshell.py:3072: DtypeWarning: Columns (0) have mixed types.Specify dtype option on import or set low_memory=False.
    # interactivity=interactivity, compiler=compiler, result=result)
# aber sie gibt mir nicht immer die Warnung, also denke ich, dass die internen Abläufe von read_csv von Hintergrundfaktoren abhängen
x = pd.read_csv(sio, low_memory=True) #, dtype={"user_id": int, "username": "string"})

x.dtypes
# das gibt:
# Out[69]: 
# user_id     object
# username    object
# dtype: object

type(x['user_id'].iloc[0]) # int
type(x['user_id'].iloc[1]) # int
type(x['user_id'].iloc[2]) # int
type(x['user_id'].iloc[10000]) # int
type(x['user_id'].iloc[299999]) # str !!!! (obwohl es eine Zahl ist! Daher muss dieser Teil als String gelesen worden sein)
type(x['user_id'].iloc[300000]) # str !!!!!

Außerdem, um ein Beispiel zu geben, in dem dies ein Problem darstellt (und wo ich zum ersten Mal auf dieses ernsthafte Problem gestoßen bin), stellen Sie sich vor, Sie haben pd.read_csv() auf eine Datei angewendet und dann Duplikate basierend auf einem Identifikator entfernen möchten. Sagen wir, der Identifikator ist manchmal numerisch, manchmal ein String. Eine Zeile könnte "81287" sein, eine andere "97324-32". Trotzdem handelt es sich um eindeutige Kennungen.

Mit low_memory=True könnte Pandas den Identifikator so einlesen:

81287
81287
81287
81287
81287
"81287"
"81287"
"81287"
"81287"
"97324-32"
"97324-32"
"97324-32"
"97324-32"
"97324-32"

Nur weil es Dinge aufteilt und deshalb ist der Identifikator 81287 manchmal eine Zahl, manchmal ein String. Wenn ich versuche, Duplikate basierend darauf zu entfernen, nun,

81287 == "81287"
Out[98]: False

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X