Panda read_csv low_memory e opzioni dtype


320

Quando si chiama

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

Ottengo:

/Users/josh/anaconda/envs/py27/lib/python2.7/site-packages/pandas/io/parsers.py:1130: DtypeWarning: le colonne (4,5,7,16) hanno tipi misti. Specificare l'opzione dtype al momento dell'importazione o impostare low_memory = False.

Perché l' dtypeopzione è correlata low_memorye perché Falseaiutarla a risolvere questo problema?


2
Ho una domanda su questo avviso. L'indice delle colonne è indicato in base 0? Ad esempio la colonna 4 che ha un tipo misto, è che df [:, 4] o df [:, 3]
maziar

@maziar durante la lettura di un csv, per impostazione predefinita viene creato e utilizzato un nuovo indice basato su 0.
firelynx,

Risposte:


433

L'opzione deprecata low_memory

L' low_memoryopzione non è adeguatamente deprecata, ma dovrebbe esserlo, poiché in realtà non fa nulla di diverso [ fonte ]

Il motivo per cui ricevi questo low_memoryavviso è perché indovinare i tipi per ogni colonna richiede molta memoria. Panda tenta di determinare quale tipo di carattere impostare analizzando i dati in ciascuna colonna.

Dtype Guessing (molto male)

I panda possono determinare quale tipo deve avere una colonna una volta letto l'intero file. Ciò significa che nulla può essere realmente analizzato prima che venga letto l'intero file a meno che non si rischi di dover modificare il tipo di quella colonna quando si legge l'ultimo valore.

Considera l'esempio di un file che ha una colonna chiamata user_id. Contiene 10 milioni di righe in cui user_id è sempre numeri. Poiché i panda non possono sapere che sono solo numeri, probabilmente lo manterranno come stringhe originali fino a quando non avrà letto l'intero file.

Specificare i tipi (dovrebbe essere sempre fatto)

aggiungendo

dtype={'user_id': int}

alla pd.read_csv()chiamata farà sapere ai panda quando inizia a leggere il file, che questo è solo numeri interi.

Vale anche la pena notare che se l'ultima riga del file fosse stata "foobar"scritta nella user_idcolonna, il caricamento si arresterebbe in modo anomalo se fosse specificato il tipo sopra indicato.

Esempio di dati non funzionanti che si interrompono quando vengono definiti i tipi

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


csvdata = """user_id,username
1,Alice
3,Bob
foobar,Caesar"""
sio = StringIO(csvdata)
pd.read_csv(sio, dtype={"user_id": int, "username": "string"})

ValueError: invalid literal for long() with base 10: 'foobar'

i dtypes sono in genere una cosa insensibile, leggi di più qui: http://docs.scipy.org/doc/numpy/reference/generated/numpy.dtype.html

Quali tipi esistono?

Abbiamo accesso ai tipi numpy: float, int, bool, timedelta64 [ns] e datetime64 [ns]. Notare che i tipi di data / ora intorpiditi non sono a conoscenza del fuso orario.

Panda estende questo set di tipi con i suoi:

'datetime64 [ns,]' Che è un timestamp consapevole del fuso orario.

'categoria' che è essenzialmente un enum (stringhe rappresentate da chiavi intere da salvare

'period []' Da non confondere con un timedelta, questi oggetti sono effettivamente ancorati a specifici periodi di tempo

'Sparse', 'Sparse [int]', 'Sparse [float]' è per dati sparsi o 'Dati che hanno molti buchi' Invece di salvare la NaN o None nel frame di dati, omette gli oggetti, risparmiando spazio .

'Intervallo' è un argomento a sé stante ma il suo uso principale è per l'indicizzazione. Vedi di più qui

'Int8', 'Int16', 'Int32', 'Int64', 'UInt8', 'UInt16', 'UInt32', 'UInt64' sono tutti interi specifici di Panda che sono nullable, a differenza della variante numpy.

'stringa' è un dtype specifico per lavorare con i dati di stringa e dà accesso .strall'attributo sulla serie.

"booleano" è come l'intorpidito "bool" ma supporta anche i dati mancanti.

Leggi il riferimento completo qui:

Riferimento del tipo di panda

Gotcha, avvertimenti, note

L'impostazione dtype=objectdisattiverà l'avviso di cui sopra, ma non renderà la memoria più efficiente, se non altro solo efficiente.

L'impostazione dtype=unicodenon farà nulla, poiché per intorpidire, a unicodeè rappresentato come object.

Utilizzo di convertitori

@sparrow indica correttamente l'uso dei convertitori per evitare che i panda esplodano quando si incontrano 'foobar'in una colonna specificata come int. Vorrei aggiungere che i convertitori sono davvero pesanti e inefficienti da usare nei panda e dovrebbero essere usati come ultima risorsa. Questo perché il processo read_csv è un singolo processo.

I file CSV possono essere elaborati riga per riga e quindi possono essere elaborati da più convertitori in parallelo in modo più efficiente semplicemente tagliando il file in segmenti ed eseguendo più processi, cosa che i panda non supportano. Ma questa è una storia diversa.


6
Quindi, dato che l'impostazione a dtype=objectnon è più efficiente in termini di memoria, c'è qualche motivo per confonderlo oltre a sbarazzarsi dell'errore?
zthomas.nc,

6
@ zthomas.nc sì, Pandas non deve preoccuparsi di provare ciò che è nella colonna. Teoricamente salvando un po 'di memoria durante il caricamento (ma nessuno dopo il completamento del caricamento) e teoricamente salvando alcuni cicli cpu (che non noterai poiché l'I / O del disco sarà il collo di bottiglia.
firelynx

5
"Vale anche la pena notare che se l'ultima riga nel file avesse" foobar "scritto nella colonna user_id, il caricamento si arresterebbe in modo anomalo se fosse specificato il tipo precedente." c'è qualche opzione "coerce" che potrebbe essere usata per buttare via questa riga invece di schiantarsi?
passero

5
@sparrow potrebbe esserci, ma l'ultima volta che l'ho usato aveva dei bug. Potrebbe essere risolto nell'ultima versione di Panda. error_bad_lines=False, warn_bad_lines=Truedovrebbe fare il trucco. La documentazione dice che è valida solo con il parser C. Dice anche che il parser predefinito è Nessuno, il che rende difficile sapere quale sia quello predefinito.
firelynx,

5
@nealmcb Puoi leggere il frame di dati con nrows=100come argomento e poi df.dtypesvedere i tipi di dati che ottieni. Tuttavia, quando si legge l'intero frame di dati con questi tipi, assicurarsi di fare in try/exceptmodo da rilevare ipotesi di tipo errate. I dati sono sporchi, sai.
firelynx,

50

Provare:

dashboard_df = pd.read_csv(p_file, sep=',', error_bad_lines=False, index_col=False, dtype='unicode')

Secondo la documentazione dei panda:

dtype: digitare il nome o il comando della colonna -> tipo

Per quanto riguarda low_memory, è True per impostazione predefinita e non è ancora documentato. Non penso sia rilevante però. Il messaggio di errore è generico, quindi non dovresti avere problemi con low_memory comunque. Spero che questo ti aiuti e fammi sapere se hai ulteriori problemi


1
Aggiunta di dtype=unicodeprodotto: NameError: name 'unicode' is not defined. Ma mettere unicodetra virgolette (come in "unicode") sembra funzionare!
sedeh

5
@sedeh È possibile specificare i tipi come tipi di pitone o come numpy.dtype('unicode'). Quando dai una stringa all'opzione dtype, proverà a lanciarla numpy.dtype()per impostazione predefinita. Specificando 'unicode'in realtà non farà nulla, gli unicode vengono semplicemente aggiornati objects. Otterraidtype='object'
firelynx il

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

Questo dovrebbe risolvere il problema. Ho avuto esattamente lo stesso errore durante la lettura di 1,8 milioni di righe da un CSV.


51
Ciò silenzia l'errore, ma in realtà non cambia nient'altro.
firelynx,

2
Ho lo stesso problema durante l'esecuzione di file di dati da 1,5 GB
Sitz Blogz,

18

Come accennato in precedenza da firelynx se dtype è esplicitamente specificato e vi sono dati misti che non sono compatibili con quel dtype, il caricamento si arresterà in modo anomalo. Ho usato un convertitore come questo come soluzione alternativa per modificare i valori con un tipo di dati incompatibile in modo che i dati possano ancora essere caricati.

def conv(val):
    if not val:
        return 0    
    try:
        return np.float64(val)
    except:        
        return np.float64(0)

df = pd.read_csv(csv_file,converters={'COL_A':conv,'COL_B':conv})

2

Ho avuto un problema simile con un file di ~ 400 MB. L'impostazione ha low_memory=Falsefatto il trucco per me. Prima fai le cose semplici, vorrei verificare che il tuo frame di dati non sia più grande della memoria del tuo sistema, riavviare, cancellare la RAM prima di procedere. Se stai ancora .csvriscontrando errori, vale la pena assicurarsi che il file sia ok, dai una rapida occhiata a Excel e assicurati che non ci sia corruzione evidente. I dati originali rotti possono provocare danni ...


1

Stavo affrontando un problema simile durante l'elaborazione di un enorme file CSV (6 milioni di righe). Ho avuto tre problemi: 1. il file conteneva strani caratteri (risolti usando la codifica) 2. il tipo di dati non era specificato (riparato usando la proprietà dtype) 3. Usando quanto sopra ho ancora affrontato un problema correlato al file_format che non poteva essere definito in base al nome del file (risolto utilizzando try .. tranne ..)

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

-1

Ha funzionato con me low_memory = Falsedurante l'importazione di un DataFrame. Questo è tutto il cambiamento che ha funzionato per me:

df = pd.read_csv('export4_16.csv',low_memory=False)
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.