Skip to content

pandas: Fissare DataFrame a un tipo specifico con astype()

Python

pandas.Series ha un tipo di dati dtype e pandas.DataFrame ha un tipo di dati diverso dtype per ogni colonna.

È possibile specificare dtype durante la creazione di un nuovo oggetto con un costruttore o la lettura da un file CSV, ecc., oppure eseguirne il cast con il metodo astype().

In questo articolo vengono descritti i seguenti contenuti.

  • Elenco dei tipi di dati di base (dtype) nei panda
  • tipo di oggetto e stringa
    • Tipo di dati speciali, oggetto
    • Nota: metodi di stringa
    • Nota:NaN
  • Trasmetti il ​​tipo di dati (dtype) con astype()
    • Trasmetti il ​​tipo di dati di pandas.Serie
    • Trasmetti il ​​tipo di dati di tutte le colonne di pandas.DataFrame
    • Trasmetti il ​​tipo di dati di qualsiasi colonna di pandas.DataFrame individualmente
  • Specificare il tipo di dati (dtype) durante la lettura di file CSV con read_csv()
    • Specificare lo stesso tipo di dati per tutte le colonne
    • Specificare il tipo di dati per ciascuna colonna
  • Conversioni di tipo implicito
    • Conversione implicita del tipo mediante operazioni aritmetiche
    • Conversione implicita del tipo per trasposizione, ecc.
    • Conversione implicita del tipo tramite assegnazione agli elementi

Vedere l’articolo seguente sui tipi di dati dtype e astype() in NumPy.

Vedere l’articolo seguente su come estrarre le colonne per dtype.

La versione panda nel codice di esempio seguente è 1.4.1. Si noti che il comportamento può variare a seconda della versione.

import pandas as pd
import numpy as np

print(pd.__version__)
# 1.4.1

Elenco dei tipi di dati di base (dtype) nei panda

Di seguito è riportato un elenco di tipi di dati di base dtype nei panda.

tipo d codice carattere descrizione
int8 i1 Intero con segno a 8 bit
int16 i2 Intero con segno a 16 bit
int32 i4 Intero con segno a 32 bit
int64 i8 Intero con segno a 64 bit
uint8 u1 Intero senza segno a 8 bit
uint16 u2 Intero senza segno a 16 bit
uint32 u4 Intero senza segno a 32 bit
uint64 u8 Intero senza segno a 64 bit
galleggiante16 f2 Numero a virgola mobile a 16 bit
galleggiante32 f4 Numero a virgola mobile a 32 bit
galleggiante64 f8 Numero a virgola mobile a 64 bit
galleggiante128 f16 Numero a virgola mobile a 128 bit
complesso64 c8 Numero a virgola mobile complesso a 64 bit
complesso128 c16 Numero a virgola mobile complesso a 128 bit
complesso256 c32 Numero a virgola mobile complesso a 256 bit
bollo ? Booleano (vero o falso)
unicode tu Stringa Unicode
oggetto o Oggetti Python

I numeri di dtype sono in bit ei numeri di codice carattere sono in byte. Si noti che i numeri sono diversi anche per lo stesso tipo.

Il codice del carattere per il tipo bool, ?, non significa sconosciuto, ma letteralmente ? è assegnato.

Quando si specifica il tipo di dati dtype, ad esempio, per il tipo float64, è consentito una delle seguenti opzioni.

  • np.float64
  • ‘flotta64’
  • ‘f8’
s = pd.Series([0, 1, 2], dtype=np.float64)
print(s.dtype)
# float64

s = pd.Series([0, 1, 2], dtype='float64')
print(s.dtype)
# float64

s = pd.Series([0, 1, 2], dtype='f8')
print(s.dtype)
# float64

Puoi specificarli con tipi Python come int, float o str senza numeri di precisione di bit.

In questo caso, viene convertito nell’equivalente dtype. Esempi in Python3, ambiente a 64 bit sono i seguenti. uint non è un tipo Python, ma è elencato insieme per comodità.

Tipo Python Esempio di dtype equivalente
int int64
galleggiante galleggiante64
str oggetto (ogni elemento è str)
(uint) uint64

Puoi usare int o float o string ‘int’, ‘float’. Non puoi usare uint perché non è un tipo Python.

s = pd.Series([0, 1, 2], dtype='float')
print(s.dtype)
# float64

s = pd.Series([0, 1, 2], dtype=float)
print(s.dtype)
# float64

s = pd.Series([0, 1, 2], dtype='uint')
print(s.dtype)
# uint64

È possibile controllare l’intervallo di valori possibili (valori minimo e massimo) per i tipi di numeri interi ea virgola mobile con np.iinfo() e np.finfo(). Per i dettagli, vedere il seguente articolo.

I tipi di dati qui introdotti sono stati forniti su NumPy, ma Pandas ha esteso dei propri dati.

tipo di oggetto e stringa

Questa descrizione sezione il tipo di oggetto e la stringa str.

Si noti che StringDtype è stato introdotto in Pandas versione 1.0.0 come tipo di dati per le stringhe. Questo tipo potrebbe diventare mainstream in futuro, ma non è menzionato qui. Vedere la documentazione ufficiale per i dettagli.

Tipo di dati speciali, oggetto

Il tipo di oggetto è un tipo di dati speciali che memorizza i puntatori agli oggetti Python. Ogni elemento può avere un tipo diverso.

Nei panda, il tipo di dati delle colonne Series e DataFrame contenenti stringhe è oggetto, ma ogni elemento ha il proprio tipo e non tutti gli elementi sono stringhe.

Esempi:

Il np.nan rappresenta il valore mancante.

La funzione incorporata type() viene applicata con il metodo map() per controllare il tipo di ogni elemento.

s_object = pd.Series([0, 'abcde', np.nan])
print(s_object)
# 0        0
# 1    abcde
# 2      NaN
# dtype: object

print(s_object.map(type))
# 0      <class 'int'>
# 1      <class 'str'>
# 2    <class 'float'>
# dtype: object

Se str è specificato in astype() (vedi sotto per i dettagli), tutti gli elementi inclusi NaN vengono convertiti in str. dtipo rimane oggetto.

s_str_astype = s_object.astype(str)
print(s_str_astype)
# 0        0
# 1    abcde
# 2      nan
# dtype: object

print(s_str_astype.map(type))
# 0    <class 'str'>
# 1    <class 'str'>
# 2    <class 'str'>
# dtype: object

Se str è specificato nel parametro dtype del costruttore, NaN rimane float. Si noti che NaN è stato convertito anche in str nella versione 0.22.0.

s_str_constructor = pd.Series([0, 'abcde', np.nan], dtype=str)
print(s_str_constructor)
# 0        0
# 1    abcde
# 2      NaN
# dtype: object

print(s_str_constructor.map(type))
# 0      <class 'str'>
# 1      <class 'str'>
# 2    <class 'float'>
# dtype: object

Nota: metodi di stringa

Si noti che anche se dtype è lo stesso tipo di oggetto, il risultato del metodo string con la funzione di accesso str è diverso a seconda del tipo di elemento.

Ad esempio, applicando str.len(), che contiene il numero di caratteri, un elemento di tipo numerico richiede NaN.

print(s_str_astype.str.len())
# 0    1
# 1    5
# 2    3
# dtype: int64

print(s_object.str.len())
# 0    NaN
# 1    5.0
# 2    NaN
# dtype: float64

Se il risultato del metodo string contiene NaN, ogni elemento potrebbe non essere str anche se il tipo di dati della colonna è oggetto. Puoi applicare astype(str) prima del metodo string.

print(s_object.astype(str).str.len())
# 0    1
# 1    5
# 2    3
# dtype: int64

Nota:NaN

Puoi rimuoverlo con dropna().

print(s_object)
# 0        0
# 1    abcde
# 2      NaN
# dtype: object

print(s_object.map(type))
# 0      <class 'int'>
# 1      <class 'str'>
# 2    <class 'float'>
# dtype: object

print(s_object.isnull())
# 0    False
# 1    False
# 2     True
# dtype: bool

print(s_object.dropna())
# 0        0
# 1    abcde
# dtype: object

Si noti che se si esegue il cast alla stringa str, NaN diventa la stringa ‘nan’ e non viene considerato come un valore mancante.

print(s_str_astype)
# 0        0
# 1    abcde
# 2      nan
# dtype: object

print(s_str_astype.map(type))
# 0    <class 'str'>
# 1    <class 'str'>
# 2    <class 'str'>
# dtype: object

print(s_str_astype.isnull())
# 0    False
# 1    False
# 2    False
# dtype: bool

print(s_str_astype.dropna())
# 0        0
# 1    abcde
# 2      nan
# dtype: object

Puoi considerarlo come un valore mancante prima del cast o sostituire la stringa ‘nan’ con NaN usando replace().

s_str_astype_nan = s_str_astype.replace('nan', np.nan)
print(s_str_astype_nan)
# 0        0
# 1    abcde
# 2      NaN
# dtype: object

print(s_str_astype_nan.map(type))
# 0      <class 'str'>
# 1      <class 'str'>
# 2    <class 'float'>
# dtype: object

print(s_str_astype_nan.isnull())
# 0    False
# 1    False
# 2     True
# dtype: bool

Trasmetti il ​​tipo di dati (dtype) con astype()

È possibile eseguire il cast del tipo di dati dtype con il metodo astype() di pandas.DataFrame, pandas.Series.

astype() fornisce un nuovo pandas.Series o pandas.DataFrame con un nuovo dtype. L’oggetto originale non viene modificato.

Utilizzare i seguenti dati come esempio.

df = pd.read_csv('data/src/sample_header.csv')
print(df)
#     a   b   c   d
# 0  11  12  13  14
# 1  21  22  23  24
# 2  31  32  33  34

s = df['c']
print(s)
# 0    13
# 1    23
# 2    33
# Name: c, dtype: int64

Trasmetti il ​​tipo di dati di pandas.Serie

Se si specifica il tipo di dati dtype nel metodo astype() di pandas.Series, viene restituito un nuovo pandas.Series. L’originale pandas.Series è rimasto invariato.

s_f = s.astype('float64')
print(s_f)
# 0    13.0
# 1    23.0
# 2    33.0
# Name: c, dtype: float64

print(s)
# 0    13
# 1    23
# 2    33
# Name: c, dtype: int64

Come accennato in precedenza, puoi specificare dtype in varie forme.

s_f = s.astype('float')
print(s_f.dtype)
# float64

s_f = s.astype(float)
print(s_f.dtype)
# float64

s_f = s.astype('f8')
print(s_f.dtype)
# float64

Trasmetti il ​​tipo di dati di tutte le colonne di pandas.DataFrame

pandas.DataFrame ha il tipo di dati dtype per ogni colonna.

Puoi controllare ogni dtype con l’attributo dtypes.

print(df)
#     a   b   c   d
# 0  11  12  13  14
# 1  21  22  23  24
# 2  31  32  33  34

print(df.dtypes)
# a    int64
# b    int64
# c    int64
# d    int64
# dtype: object

Se specifichi il tipo di dati dtype nel metodo astype() di pandas.DataFrame, i tipi di dati di tutte le colonne vengono modificate.

df_f = df.astype('float64')
print(df_f)
#       a     b     c     d
# 0  11.0  12.0  13.0  14.0
# 1  21.0  22.0  23.0  24.0
# 2  31.0  32.0  33.0  34.0

print(df_f.dtypes)
# a    float64
# b    float64
# c    float64
# d    float64
# dtype: object

Trasmetti il ​​tipo di dati di qualsiasi colonna di pandas.DataFrame individualmente

È possibile modificare il tipo di dati dtype di qualsiasi colonna individualmente specificando un dizionario di {nome colonna: tipo di dati} in astype().

df_fcol = df.astype({'a': float})
print(df_fcol)
#       a   b   c   d
# 0  11.0  12  13  14
# 1  21.0  22  23  24
# 2  31.0  32  33  34

print(df_fcol.dtypes)
# a    float64
# b      int64
# c      int64
# d      int64
# dtype: object

df_fcol2 = df.astype({'a': 'float32', 'c': 'int8'})
print(df_fcol2)
#       a   b   c   d
# 0  11.0  12  13  14
# 1  21.0  22  23  24
# 2  31.0  32  33  34

print(df_fcol2.dtypes)
# a    float32
# b      int64
# c       int8
# d      int64
# dtype: object

Specificare il tipo di dati (dtype) durante la lettura di file CSV con read_csv()

Nei panda, puoi leggere i file CSV con pd.read_csv(). È possibile specificare tipo di dati con il parametro qualsiasi tipo.

Usa il seguente file CSV come esempio.

,a,b,c,d
ONE,1,"001",100,x
TWO,2,"020",,y
THREE,3,"300",300,z

Se l’argomento dtype viene omesso, il tipo di dati viene scelto automaticamente per ciascuna colonna.

df = pd.read_csv('data/src/sample_header_index_dtype.csv', index_col=0)
print(df)
#        a    b      c  d
# ONE    1    1  100.0  x
# TWO    2   20    NaN  y
# THREE  3  300  300.0  z

print(df.dtypes)
# a      int64
# b      int64
# c    float64
# d     object
# dtype: object

print(df.applymap(type))
#                    a              b                c              d
# ONE    <class 'int'>  <class 'int'>  <class 'float'>  <class 'str'>
# TWO    <class 'int'>  <class 'int'>  <class 'float'>  <class 'str'>
# THREE  <class 'int'>  <class 'int'>  <class 'float'>  <class 'str'>

Specificare lo stesso tipo di dati per tutte le colonne

Se si specifica un tipo di dati per il parametro dtype, tutte le colonne vengono convertite in quel tipo.

Se sono presenti colonne che non possono essere convertite nel tipo di dati specificato, viene generato un errore.

# pd.read_csv('data/src/sample_header_index_dtype.csv',
#             index_col=0, dtype=float)
# ValueError: could not convert string to float: 'ONE'

Se dtype=str, il valore mancante NaN non viene convertito in str.

df_str = pd.read_csv('data/src/sample_header_index_dtype.csv',
                     index_col=0, dtype=str)
print(df_str)
#        a    b    c  d
# ONE    1  001  100  x
# TWO    2  020  NaN  y
# THREE  3  300  300  z

print(df_str.dtypes)
# a    object
# b    object
# c    object
# d    object
# dtype: object

print(df_str.applymap(type))
#                    a              b                c              d
# ONE    <class 'str'>  <class 'str'>    <class 'str'>  <class 'str'>
# TWO    <class 'str'>  <class 'str'>  <class 'float'>  <class 'str'>
# THREE  <class 'str'>  <class 'str'>    <class 'str'>  <class 'str'>

Se vuoi un valore mancante nella stringa ‘nan’, leggilo senza specificare dtype e poi lancialo su str con astype().

print(df.astype(str).applymap(type))
#                    a              b              c              d
# ONE    <class 'str'>  <class 'str'>  <class 'str'>  <class 'str'>
# TWO    <class 'str'>  <class 'str'>  <class 'str'>  <class 'str'>
# THREE  <class 'str'>  <class 'str'>  <class 'str'>  <class 'str'>

Specificare il tipo di dati per ciascuna colonna

Come con astype(), puoi usare un dizionario per specificare il tipo di dati per ogni colonna in read_csv().

df_col = pd.read_csv('data/src/sample_header_index_dtype.csv',
                     index_col=0, dtype={'a': str, 'b': float})
print(df_col)
#        a      b      c  d
# ONE    1    1.0  100.0  x
# TWO    2   20.0    NaN  y
# THREE  3  300.0  300.0  z

print(df_col.dtypes)
# a     object
# b    float64
# c    float64
# d     object
# dtype: object

È possibile specificare per numero di colonna anziché per nome di colonna. Si noti che se viene specificata una colonna di indice, è necessario specificare il numero di colonna inclusa la colonna di indice.

df_col = pd.read_csv('data/src/sample_header_index_dtype.csv',
                     index_col=0, dtype={1: str, 2: float})
print(df_col)
#        a      b      c  d
# ONE    1    1.0  100.0  x
# TWO    2   20.0    NaN  y
# THREE  3  300.0  300.0  z

print(df_col.dtypes)
# a     object
# b    float64
# c    float64
# d     object
# dtype: object

Conversioni di tipo implicito

Oltre alla conversione esplicita del tipo tramite astype(), i tipi di dati possono essere convertiti in modo implicito da varie operazioni.

Usa pandas.DataFrame con colonne di int intero e colonne di float in virgola mobile come esempio.

df_mix = pd.DataFrame({'col_int': [0, 1, 2], 'col_float': [0.0, 0.1, 0.2]}, index=['A', 'B', 'C'])
print(df_mix)
#    col_int  col_float
# A        0        0.0
# B        1        0.1
# C        2        0.2

print(df_mix.dtypes)
# col_int        int64
# col_float    float64
# dtype: object

Conversione implicita del tipo mediante operazioni aritmetiche

Ad esempio, il risultato dell’aggiunta da parte dell’operatore + di una colonna int a una colonna float è un float.

print(df_mix['col_int'] + df_mix['col_float'])
# A    0.0
# B    1.1
# C    2.2
# dtype: float64

Allo stesso modo, le operazioni con valori scalari convertono implicitamente il tipo di dati. Il risultato della divisione da parte dell’operatore / è float.

print(df_mix / 1)
#    col_int  col_float
# A      0.0        0.0
# B      1.0        0.1
# C      2.0        0.2

print((df_mix / 1).dtypes)
# col_int      float64
# col_float    float64
# dtype: object

Per +, -, *, // e **, le operazioni tra numeri interi restituiscono int e le operazioni che coinvolgono numeri a virgola mobile restituiscono float. Ciò equivale alla conversione di tipo implicita dell’array NumPy ndarray.

print(df_mix * 1)
#    col_int  col_float
# A        0        0.0
# B        1        0.1
# C        2        0.2

print((df_mix * 1).dtypes)
# col_int        int64
# col_float    float64
# dtype: object

print(df_mix * 1.0)
#    col_int  col_float
# A      0.0        0.0
# B      1.0        0.1
# C      2.0        0.2

print((df_mix * 1.0).dtypes)
# col_int      float64
# col_float    float64
# dtype: object

Conversione implicita del tipo per trasposizione, ecc.

Il tipo può anche essere convertito quando una riga viene selezionata come pandas.Series con loc o iloc, o quando pandas.DataFrame viene trasposto con To transpose(). Ad esempio, un elemento intero viene convertito in un numero a virgola mobile.

print(df_mix.loc['A'])
# col_int      0.0
# col_float    0.0
# Name: A, dtype: float64

print(df_mix.T)
#              A    B    C
# col_int    0.0  1.0  2.0
# col_float  0.0  0.1  0.2

print(df_mix.T.dtypes)
# A    float64
# B    float64
# C    float64
# dtype: object

Conversione implicita del tipo tramite assegnazione agli elementi

Il tipo di dati può anche essere convertito implicitamente quando si assegna un valore a un elemento.

Ad esempio, assegnando un elemento di float a una colonna di int individua quella colonna in float. Inoltre, l’assegnazione di un elemento di int a una colonna di float converte quell’elemento in float.

df_mix.at['A', 'col_int'] = 10.1
df_mix.at['A', 'col_float'] = 10
print(df_mix)
#    col_int  col_float
# A     10.1       10.0
# B      1.0        0.1
# C      2.0        0.2

print(df_mix.dtypes)
# col_int      float64
# col_float    float64
# dtype: object

Quando un elemento stringa viene assegnato a una colonna numerica, viene eseguito il cast del tipo di dati della colonna su oggetto.

df_mix.at['A', 'col_float'] = 'abc'
print(df_mix)
#    col_int col_float
# A     10.1       abc
# B      1.0       0.1
# C      2.0       0.2

print(df_mix.dtypes)
# col_int      float64
# col_float     object
# dtype: object

print(df_mix.applymap(type))
#            col_int        col_float
# A  <class 'float'>    <class 'str'>
# B  <class 'float'>  <class 'float'>
# C  <class 'float'>  <class 'float'>

Si noti che il codice di esempio sopra è il risultato della versione 1.4.1. Nella versione 0.22.0, il tipo di colonna è rimasto lo stesso anche dopo aver assegnato un elemento di tipo diverso, ma il tipo dell’elemento assegnato è cambiato. Si noti che il comportamento varia a seconda della versione.