Come rilevare automaticamente le colonne Data/Datetime e impostare il loro tipo di dati durante la lettura di un file CSV in Pandas

Nodo di origine: 1106147

Come rilevare automaticamente le colonne Data/Datetime e impostare il loro tipo di dati durante la lettura di un file CSV in Pandas

Quando read_csv() legge ad esempio "2021-03-04" e "2021-03-04 21:37:01.123" come semplici tipi di dati "oggetto", spesso puoi semplicemente convertirli automaticamente tutti in una volta in veri tipi di dati datetime.


By David B Rosen (dottorato), Lead Data Scientist per l'approvazione automatizzata del credito presso IBM Global Financing



Diciamo che ho un file di dati CSV che voglio leggere in un dataframe Pandas e alcune delle sue colonne sono date o datetime, ma non voglio preoccuparmi di identificare/specificare in anticipo i nomi di queste colonne. Invece vorrei ottenere automaticamente i tipi di dati mostrati nel df.info() uscita nella foto sopra, dove sono state le colonne appropriate automaticamente dato un tipo di dati datetime (caselle di contorno verdi). Ecco come realizzarlo:

from dt_auto import read_csv
df=read_csv('myfile.csv')

Nota che l'ho fatto non invocare direttamente pd.read_csv (la versione Panda di read_csv). La mia funzione dt_auto.read_csv (vedi il suo codice in basso) ha invocato pd.read_csv() stesso e quindi ha rilevato e convertito automaticamente il tipo di dati delle due colonne datetime rilevate. (Il contenuto di questo df verrà mostrato in basso.)

Se avessi usato i normali Panda pd.read_csv(), avrei ottenuto per impostazione predefinita solo tipi di dati di oggetti generici come di seguito (caselle di contorno rosse):

from pandas import read_csv
df=read_csv('myfile.csv')
df.info()



Nota che l'unica differenza dal codice originale è nell'istruzione import, dove ho cambiato "from dt_auto" in "from pandas". Questo è sufficiente fintanto che usi solo "=read_csv()" in tutto, non qualificandolo come "=pd.read_csv()" o "=dt_auto.read_csv()".

Ecco il contenuto del mio dt_auto.py ("data e ora automatica"):

import pandas as pd
def dt_inplace(df): """Automatically detect and convert (in place!) each dataframe column of datatype 'object' to a datetime just when ALL of its non-NaN values can be successfully parsed by pd.to_datetime(). Also returns a ref. to df for convenient use in an expression. """ from pandas.errors import ParserError for c in df.columns[df.dtypes=='object']: #don't cnvt num try: df[c]=pd.to_datetime(df[c]) except (ParserError,ValueError): #Can't cnvrt some pass # ...so leave whole column as-is unconverted return df
def read_csv(*args, **kwargs): """Drop-in replacement for Pandas pd.read_csv. It invokes pd.read_csv() (passing its arguments) and then auto- matically detects and converts each column whose datatype is 'object' to a datetime just when ALL of the column's non-NaN values can be successfully parsed by pd.to_datetime(), and returns the resulting dataframe. """ return dt_inplace(pd.read_csv(*args, **kwargs))

Ma non è rischioso? E se una delle colonne non fosse interamente una colonna datetime? Ovviamente potresti avere alcune stringhe oscure che sembrano semplicemente date ma non lo sono, ma non c'è molto rischio che questo codice converta alla cieca o perda stringhe non datetime, per due motivi:

  1. Questo codice sarà non convertire qualsiasi valore in una colonna a meno che ogni il valore non NaN in questa colonna può essere analizzato con successo da pd.to_datetime e convertito in un datetime. In altre parole, non gli permetteremo mai di convertire una stringa in un pd.NaT (il risultato di "fallimento") perché non può interpretarlo come un datetime.
  2. Lo farà non tentare di convertire colonne che sono già state interpretate come di qualsiasi tipo diverso da oggetto, ovvero qualsiasi tipo specifico come int64 o float64, anche se pd.to_datetime avrebbe felicemente (ma probabilmente indesiderabile) convertito un numero come 2000 alla data 2000-01 -01.

Nella mia esperienza finora, la funzione dt_auto.read_csv non richiede molto tempo per essere eseguita su un tipico frame di dati. Anche se ci sono molte colonne oggetto (stringa) non datetime, incontra quasi sempre molto rapidamente un valore vicino alla parte superiore di ciascuna di queste colonne che non può analizzare come datetime e si arrende e passa alla colonna successiva senza tentare di analizzare il resto dei valori della colonna.

Ecco come appare il dataframe risultante da dt_auto.read_csv(), sebbene non si possa necessariamente dire guardandolo che le due colonne appropriate sono effettivamente tipi di dati datetime. Si dà il caso che il file CSV avesse un numero variabile di posizioni decimali (tre, nessuna e nove) per i secondi in Update_Timestamp, ma il tipo di dati datetime stesso mostra nove di queste cifre a prescindere. La data di nascita nel file csv infatti aveva solo date (nessuna ora) ma era memorizzata come data e ora completa, con zeri per le ore, i minuti e i secondi (incluso lo zero come parte decimale), ma tutte le componenti temporali nella colonna essendo zero, Pandas visualizza solo la data (anno-mese-giorno) per questa colonna.



Ovviamente pd.to_datetime, e quindi dt_auto.read_csv, non può gestire tutti i possibili formati di data e data e ora per impostazione predefinita, ma gestirà molti formati comuni non ambigui (generalmente anno mese giorno) come quelli scritti dal metodo dataframe.to_csv e molti altri strumenti, inclusi molti formati ISO datetime (che generalmente hanno una "T" che separa la data dall'ora anziché uno spazio). Non ho sperimentato datetime che includono informazioni sul fuso orario perché di solito non vedo dati del genere, ma per favore fatemi sapere in un commento di risposta se questi potrebbero essere gestiti meglio da ulteriori modifiche al codice.

Cosa ne pensi? Hai trovato utile questo piccolo articolo? E lo stesso Panda dovrebbe aggiungere (ad esempio alla stessa funzione pd.read_csv?) la possibilità di farlo opzionalmente per noi in modo da non dover copiare/importare il mio codice dt_auto.py sopra? Sarei felice di vedere i tuoi commenti e domande come risposte qui.

 
Grazie a Elliot Gunn.

 
Bio: David B Rosen (dottorato) è Lead Data Scientist per l'approvazione automatizzata del credito presso IBM Global Financing. Trova altri scritti di David su dabruro.medium.com.

Originale. Ripubblicato con il permesso.

Correlato:

Fonte: https://www.kdnuggets.com/2021/10/auto-detect-date-datetime-columns-and-set-their-datatype-when-reading-a-csv-file-in-pandas.html

Timestamp:

Di più da KDnuggets