Hai tre opzioni principali per convertire i tipi in panda:
to_numeric()
- fornisce funzionalità per convertire in modo sicuro tipi non numerici (ad esempio stringhe) in un tipo numerico adatto. (Vedi anche to_datetime()
e to_timedelta()
.)
astype()
- convertire (quasi) qualsiasi tipo in (quasi) qualsiasi altro tipo (anche se non è necessariamente sensato farlo). Ti consente anche di convertire in tipi categoriali (molto utile).
infer_objects()
- un metodo di utilità per convertire colonne di oggetti che contengono oggetti Python in un tipo di panda, se possibile.
Continua a leggere per spiegazioni più dettagliate e l'utilizzo di ciascuno di questi metodi.
1. to_numeric()
Il modo migliore per convertire una o più colonne di un DataFrame in valori numerici è utilizzare pandas.to_numeric()
.
Questa funzione tenterà di modificare gli oggetti non numerici (come le stringhe) in numeri interi o numeri in virgola mobile, a seconda dei casi.
Utilizzo di base
L'input per to_numeric()
è una serie o una singola colonna di un DataFrame.
>>> s = pd.Series(["8", 6, "7.5", 3, "0.9"]) # mixed string and numeric values
>>> s
0 8
1 6
2 7.5
3 3
4 0.9
dtype: object
>>> pd.to_numeric(s) # convert everything to float values
0 8.0
1 6.0
2 7.5
3 3.0
4 0.9
dtype: float64
Come puoi vedere, viene restituita una nuova serie. Ricorda di assegnare questo output a un nome di variabile o colonna per continuare a usarlo:
# convert Series
my_series = pd.to_numeric(my_series)
# convert column "a" of a DataFrame
df["a"] = pd.to_numeric(df["a"])
Puoi anche usarlo per convertire più colonne di un DataFrame tramite il apply()
metodo:
# convert all columns of DataFrame
df = df.apply(pd.to_numeric) # convert all columns of DataFrame
# convert just columns "a" and "b"
df[["a", "b"]] = df[["a", "b"]].apply(pd.to_numeric)
Finché i tuoi valori possono essere tutti convertiti, probabilmente è tutto ciò di cui hai bisogno.
Gestione degli errori
Ma cosa succede se alcuni valori non possono essere convertiti in un tipo numerico?
to_numeric()
accetta anche un errors
argomento di parole chiave che consente di forzare valori non numerici NaN
o semplicemente ignorare le colonne che contengono questi valori.
Ecco un esempio usando una serie di stringhe s
che ha il tipo di oggetto:
>>> s = pd.Series(['1', '2', '4.7', 'pandas', '10'])
>>> s
0 1
1 2
2 4.7
3 pandas
4 10
dtype: object
Il comportamento predefinito è aumentare se non è possibile convertire un valore. In questo caso, non può far fronte alla stringa "panda":
>>> pd.to_numeric(s) # or pd.to_numeric(s, errors='raise')
ValueError: Unable to parse string
Piuttosto che fallire, potremmo volere che i "panda" siano considerati un valore numerico mancante / cattivo. Possiamo forzare i valori non validi NaN
come segue usando l' errors
argomento keyword:
>>> pd.to_numeric(s, errors='coerce')
0 1.0
1 2.0
2 4.7
3 NaN
4 10.0
dtype: float64
La terza opzione per errors
è semplicemente ignorare l'operazione se viene rilevato un valore non valido:
>>> pd.to_numeric(s, errors='ignore')
# the original Series is returned untouched
Quest'ultima opzione è particolarmente utile quando si desidera convertire l'intero DataFrame, ma non si sa quale delle nostre colonne può essere convertita in modo affidabile in un tipo numerico. In tal caso basta scrivere:
df.apply(pd.to_numeric, errors='ignore')
La funzione verrà applicata a ciascuna colonna di DataFrame. Le colonne che possono essere convertite in un tipo numerico verranno convertite, mentre le colonne che non possono (ad esempio contengono stringhe o cifre non numeriche) verranno lasciate sole.
downcasting
Per impostazione predefinita, la conversione con to_numeric()
ti darà un int64
o un float64
tipo (o qualsiasi larghezza intera sia nativa per la tua piattaforma).
Di solito è quello che vuoi, ma se volessi risparmiare un po 'di memoria e utilizzare un dtype più compatto, come float32
, o int8
?
to_numeric()
ti dà la possibilità di effettuare il downcast su 'intero', 'firmato', 'non firmato', 'float'. Ecco un esempio per una semplice serie s
di tipo intero:
>>> s = pd.Series([1, 2, -7])
>>> s
0 1
1 2
2 -7
dtype: int64
Il downcasting su "intero" utilizza il numero intero più piccolo possibile che può contenere i valori:
>>> pd.to_numeric(s, downcast='integer')
0 1
1 2
2 -7
dtype: int8
Il downcasting su "float" seleziona allo stesso modo un tipo mobile più piccolo del normale:
>>> pd.to_numeric(s, downcast='float')
0 1.0
1 2.0
2 -7.0
dtype: float32
2. astype()
Il astype()
metodo consente di essere espliciti sul tipo che si desidera avere DataFrame o Series. È molto versatile in quanto puoi provare a passare da un tipo all'altro.
Utilizzo di base
Basta scegliere un tipo: è possibile utilizzare un tipo NumPy (ad esempio np.int16
), alcuni tipi di Python (ad esempio bool) o tipi specifici di panda (come il tipo di categoria).
Chiama il metodo sull'oggetto che desideri convertire e astype()
proverà a convertirlo per te:
# convert all DataFrame columns to the int64 dtype
df = df.astype(int)
# convert column "a" to int64 dtype and "b" to complex type
df = df.astype({"a": int, "b": complex})
# convert Series to float16 type
s = s.astype(np.float16)
# convert Series to Python strings
s = s.astype(str)
# convert Series to categorical type - see docs for more details
s = s.astype('category')
Nota che ho detto "prova" - se astype()
non sa come convertire un valore in Series o DataFrame, genererà un errore. Ad esempio, se hai un valore NaN
o inf
, visualizzerai un errore nel tentativo di convertirlo in un numero intero.
A partire da Panda 0.20.0, questo errore può essere eliminato passando errors='ignore'
. Il tuo oggetto originale verrà restituito intatto.
Stai attento
astype()
è potente, ma a volte converte i valori "in modo errato". Per esempio:
>>> s = pd.Series([1, 2, -7])
>>> s
0 1
1 2
2 -7
dtype: int64
Questi sono numeri interi piccoli, quindi che ne dite di convertire in un tipo a 8 bit senza segno per risparmiare memoria?
>>> s.astype(np.uint8)
0 1
1 2
2 249
dtype: uint8
La conversione ha funzionato, ma il -7 è stato concluso per diventare 249 (ovvero 2 8 - 7)!
Cercare di eseguire il downcast usando pd.to_numeric(s, downcast='unsigned')
invece potrebbe aiutare a prevenire questo errore.
3. infer_objects()
La versione 0.21.0 di Panda ha introdotto il metodo infer_objects()
per convertire le colonne di un DataFrame che ha un tipo di dati oggetto in un tipo più specifico (conversioni soft).
Ad esempio, ecco un DataFrame con due colonne di tipo oggetto. Uno contiene numeri interi reali e l'altro contiene stringhe che rappresentano numeri interi:
>>> df = pd.DataFrame({'a': [7, 1, 5], 'b': ['3','2','1']}, dtype='object')
>>> df.dtypes
a object
b object
dtype: object
Usando infer_objects()
, puoi cambiare il tipo di colonna 'a' in int64:
>>> df = df.infer_objects()
>>> df.dtypes
a int64
b object
dtype: object
La colonna 'b' è stata lasciata sola poiché i suoi valori erano stringhe, non numeri interi. Se si desidera provare a forzare la conversione di entrambe le colonne in un tipo intero, è possibile utilizzare df.astype(int)
invece.