type - python pandas cast column




Cambia il tipo di dati delle colonne in Panda (4)

Che ne dici di creare due dataframes, ciascuno con tipi di dati diversi per le loro colonne e quindi accodarli insieme?

In[8}:  d1.dtypes
Out[8]: 
float_column     float64
string_column     object
dtype: object

risultati

dataframe = dataframe.astype({'col_name_1':'int','col_name_2':'float64', etc. ...})

Dopo aver creato il dataframe, puoi popolarlo con variabili a virgola mobile nella prima colonna e stringhe (o qualsiasi tipo di dati desiderato) nella seconda colonna.

Voglio convertire una tabella, rappresentata come una lista di liste, in un DataFrame di Pandas. Come esempio estremamente semplificato:

a = [['a', '1.2', '4.2'], ['b', '70', '0.03'], ['x', '5', '0']]
df = pd.DataFrame(a)

Qual è il modo migliore per convertire le colonne in tipi appropriati, in questo caso le colonne 2 e 3 in float? C'è un modo per specificare i tipi durante la conversione in DataFrame? O è meglio creare prima DataFrame e quindi scorrere le colonne per modificare il tipo per ogni colonna? Idealmente mi piacerebbe farlo in modo dinamico perché ci possono essere centinaia di colonne e non voglio specificare esattamente quali colonne sono di quale tipo. Tutto quello che posso garantire è che ogni colonna contiene valori dello stesso tipo.


Cosa ne pensi di questo?

df[['col.name1', 'col.name2'...]] = df[['col.name1', 'col.name2'..]].astype('data_type')

Hai tre opzioni principali per convertire i tipi in panda.

1. to_numeric()

Il modo migliore per convertire una o più colonne di un DataFrame in valori numerici consiste nell'utilizzare pandas.to_numeric() .

Questa funzione proverà a cambiare gli oggetti non numerici (come le stringhe) in numeri interi o in virgola mobile come appropriato.

Utilizzo di base

L'input to to_numeric() è una serie o una singola colonna di un DataFrame.

# convert Series
my_series = pd.to_numeric(my_series)

# convert column "a" of a DataFrame
df["a"] = pd.to_numeric(df["a"])

Come puoi vedere, viene restituita una nuova serie. Ricorda di assegnare questo output a un nome di variabile o colonna per continuare ad usarlo:

# 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)

Puoi anche usarlo per convertire più colonne di un DataFrame tramite il metodo apply() :

>>> s = pd.Series(['1', '2', '4.7', 'pandas', '10'])
>>> s
0         1
1         2
2       4.7
3    pandas
4        10
dtype: object

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 argomento di parole chiave di errors che consente di forzare i valori non numerici come NaN o semplicemente di ignorare le colonne che contengono questi valori.

Ecco un esempio usando una serie di stringhe s che ha il tipo di oggetto:

>>> pd.to_numeric(s) # or pd.to_numeric(s, errors='raise')
ValueError: Unable to parse string

Il comportamento predefinito è di aumentare se non può convertire un valore. In questo caso, non può far fronte alla stringa "panda":

>>> pd.to_numeric(s, errors='coerce')
0     1.0
1     2.0
2     4.7
3     NaN
4    10.0
dtype: float64

Anziché fallire, potremmo volere che i "panda" siano considerati un valore numerico mancante / errato. Possiamo forzare i valori non validi a NaN come segue usando l'argomento della parola chiave errors :

>>> pd.to_numeric(s, errors='ignore')
# the original Series is returned untouched

La terza opzione per gli errors è solo per ignorare l'operazione se viene rilevato un valore non valido:

df.apply(pd.to_numeric, errors='ignore')

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, scrivi:

>>> s = pd.Series([1, 2, -7])
>>> s
0    1
1    2
2   -7
dtype: int64

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 date non numeriche) saranno lasciate in pace.

downcasting

Per impostazione predefinita, la conversione con to_numeric() ti darà un int64 o float64 (o qualsiasi altra larghezza di un intero è nativa per la tua piattaforma).

Di solito è quello che vuoi, ma se volessi salvare un po 'di memoria e usare un dtype più compatto, come float32 o int8 ?

to_numeric() ti dà la possibilità di downcast a 'intero', 'firmato', 'unsigned', 'float'. Ecco un esempio per una serie semplice di tipo intero:

>>> pd.to_numeric(s, downcast='integer')
0    1
1    2
2   -7
dtype: int8

Downcasting a 'integer' utilizza il numero intero più piccolo possibile che può contenere i valori:

>>> pd.to_numeric(s, downcast='float')
0    1.0
1    2.0
2   -7.0
dtype: float32

Downcasting a 'float' seleziona in modo simile un tipo di floating più piccolo del normale:

# 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')

2. astype()

Il metodo astype() ti permette di essere esplicito riguardo al dtype che vuoi che il tuo DataFrame o la tua Serie abbiano. È molto versatile in quanto puoi provare e passare da un tipo all'altro.

Utilizzo di base

Scegli un tipo: puoi usare un dtype NumPy (ad es. np.int16 ), alcuni tipi Python (es. np.int16 ) o tipi specifici di panda (come il dtype categoriale).

Chiama il metodo sull'oggetto che vuoi convertire e astype() proverà a convertirlo per te:

>>> s = pd.Series([1, 2, -7])
>>> s
0    1
1    2
2   -7
dtype: int64

Notate che ho detto "try" - se astype() non sa come convertire un valore in Series o DataFrame, genererà un errore. Ad esempio se hai un valore NaN o inf riceverai un errore nel tentativo di convertirlo in un numero intero.

A partire da panda 0.20.0, questo errore può essere soppresso passando errors='ignore' . Il tuo oggetto originale sarà restituito intatto.

Stai attento

astype() è potente, ma a volte converte i valori "erroneamente". Per esempio:

>>> s.astype(np.uint8)
0      1
1      2
2    249
dtype: uint8

Questi sono piccoli numeri interi, quindi che ne dici di convertirli in un tipo a 8 bit senza segno per risparmiare memoria?

>>> df = pd.DataFrame({'a': [7, 1, 5], 'b': ['3','2','1']}, dtype='object')
>>> df.dtypes
a    object
b    object
dtype: object

La conversione ha funzionato, ma il -7 è stato diviso per diventare 249 (cioè 2 8 - 7)!

Provare a downcast utilizzando invece pd.to_numeric(s, downcast='unsigned') potrebbe aiutare a prevenire questo errore.

3. infer_objects()

La versione 0.21.0 di panda ha introdotto il metodo infer_objects() per la conversione di colonne di un DataFrame che hanno un tipo di dati oggetto in un tipo più specifico (conversioni software).

Ad esempio, ecco un DataFrame con due colonne di tipo di oggetto. Uno contiene interi effettivi e l'altro contiene stringhe che rappresentano numeri interi:

>>> df = df.infer_objects()
>>> df.dtypes
a     int64
b    object
dtype: object

Usando infer_objects() , puoi cambiare il tipo di colonna 'a' in int64:

a = [['a', '1.2', '4.2'], ['b', '70', '0.03'], ['x', '5', '0']]
df = pd.DataFrame(a, columns=['one', 'two', 'three'])
df
Out[16]: 
  one  two three
0   a  1.2   4.2
1   b   70  0.03
2   x    5     0

df.dtypes
Out[17]: 
one      object
two      object
three    object

df[['two', 'three']] = df[['two', 'three']].astype(float)

df.dtypes
Out[19]: 
one       object
two      float64
three    float64

La colonna 'b' è stata lasciata in quanto i suoi valori erano stringhe, non interi. Se si desidera provare e forzare la conversione di entrambe le colonne in un tipo intero, è possibile utilizzare df.astype(int) .


Quando ho solo bisogno di specificare colonne specifiche, e voglio essere esplicito, ho usato (per posizione dei documenti):

a = [['a', '1.2', '4.2'], ['b', '70', '0.03'], ['x', '5', '0']]
df = pd.DataFrame(a, columns=['col_name_1', 'col_name_2', 'col_name_3'])
df = df.astype({'col_name_2':'float64', 'col_name_3':'float64'})

Quindi, usando la domanda originale, ma fornendo i nomi delle colonne ad essa ...

 a = [['a', '1.2', '4.2'], ['b', '70', '0.03'], ['x', '5', '0']] df = pd.DataFrame(a, columns=['col_name_1', 'col_name_2', 'col_name_3']) df = df.astype({'col_name_2':'float64', 'col_name_3':'float64'}) 




casting