Prima di Panda 1.0 (bene, 0,25 in realtà) questo era il modo defacto di dichiarare una Serie / colonna come stringa:
# pandas <= 0.25
# Note to pedants: specifying the type is unnecessary since pandas will
# automagically infer the type as object
s = pd.Series(['a', 'b', 'c'], dtype=str)
s.dtype
# dtype('O')
Da Panda 1.0 in poi, considera invece l' uso di "string"
type .
# pandas >= 1.0
s = pd.Series(['a', 'b', 'c'], dtype="string")
s.dtype
# StringDtype
Ecco perché, come citato dai documenti:
È possibile memorizzare accidentalmente una combinazione di stringhe e non stringhe in un array di tipi di oggetto. È meglio avere un dtype dedicato.
object
dtype interrompe operazioni specifiche del dtype come DataFrame.select_dtypes()
. Non esiste un modo chiaro per selezionare solo il testo escludendo le colonne non di testo ma ancora di tipo oggetto.
Durante la lettura del codice, il contenuto di un object
array dtype è meno chiaro di 'string'
.
Vedi anche la sezione sulle differenze comportamentali tra "string"
eobject
.
I tipi di estensione (introdotti in 0.24 e formalizzati in 1.0) sono più vicini ai panda che al numpy, il che è positivo perché i tipi numpy non sono abbastanza potenti. Ad esempio NumPy non ha alcun modo di rappresentare i dati mancanti in dati interi (poiché type(NaN) == float
). Ma i panda possono usare le colonne Nullable Integer .
Perché dovrei smettere di usarlo?
Miscelazione accidentale di tipi di dati
Il primo motivo, come indicato nei documenti, è che è possibile archiviare accidentalmente dati non testuali nelle colonne degli oggetti.
# pandas <= 0.25
pd.Series(['a', 'b', 1.23]) # whoops, this should have been "1.23"
0 a
1 b
2 1.23
dtype: object
pd.Series(['a', 'b', 1.23]).tolist()
# ['a', 'b', 1.23] # oops, pandas was storing this as float all the time.
# pandas >= 1.0
pd.Series(['a', 'b', 1.23], dtype="string")
0 a
1 b
2 1.23
dtype: string
pd.Series(['a', 'b', 1.23], dtype="string").tolist()
# ['a', 'b', '1.23'] # it's a string and we just averted some potentially nasty bugs.
Sfidare a differenziare stringhe e altri oggetti in pitone
Un altro esempio ovvio è che è più difficile distinguere tra "stringhe" e "oggetti". Gli oggetti sono essenzialmente il tipo di coperta per qualsiasi tipo che non supporta operazioni vettorializzabili .
Tener conto di,
# Setup
df = pd.DataFrame({'A': ['a', 'b', 'c'], 'B': [{}, [1, 2, 3], 123]})
df
A B
0 a {}
1 b [1, 2, 3]
2 c 123
Fino ai panda 0.25, praticamente non c'era modo di distinguere che "A" e "B" non hanno lo stesso tipo di dati.
# pandas <= 0.25
df.dtypes
A object
B object
dtype: object
df.select_dtypes(object)
A B
0 a {}
1 b [1, 2, 3]
2 c 123
Da Panda 1.0, questo diventa molto più semplice:
# pandas >= 1.0
# Convenience function I call to help illustrate my point.
df = df.convert_dtypes()
df.dtypes
A string
B object
dtype: object
df.select_dtypes("string")
A
0 a
1 b
2 c
Leggibilità
Si spiega da sé ;-)
OK, quindi dovrei smettere di usarlo adesso?
...No. Al momento della stesura di questa risposta (versione 1.1), non ci sono vantaggi in termini di prestazioni, ma i documenti prevedono miglioramenti futuri per migliorare significativamente le prestazioni e ridurre l'utilizzo della memoria per le "string"
colonne rispetto agli oggetti. Detto questo, tuttavia, non è mai troppo presto per formare buone abitudini!
astype("string")
invece cheastype(str)
per alcuni buoni motivi, dai un'occhiata.