Stringhe in un DataFrame, ma dtype è un oggetto


96

Perché i Panda mi dicono che ho oggetti, sebbene ogni elemento nella colonna selezionata sia una stringa, anche dopo una conversione esplicita.

Questo è il mio DataFrame:

<class 'pandas.core.frame.DataFrame'>
Int64Index: 56992 entries, 0 to 56991
Data columns (total 7 columns):
id            56992  non-null values
attr1         56992  non-null values
attr2         56992  non-null values
attr3         56992  non-null values
attr4         56992  non-null values
attr5         56992  non-null values
attr6         56992  non-null values
dtypes: int64(2), object(5)

Cinque di loro lo sono dtype object. Converto esplicitamente quegli oggetti in stringhe:

for c in df.columns:
    if df[c].dtype == object:
        print "convert ", df[c].name, " to string"
        df[c] = df[c].astype(str)

Quindi, df["attr2"]ha ancora dtype object, anche se type(df["attr2"].ix[0]rivela str, il che è corretto.

Pandas distingue tra int64e float64e object. Qual è la logica dietro quando non c'è dtype str? Perché è strcoperto da object?


Sono venuto qui perché i join non riescono a causa del "tipo di oggetto" anche se ogni stringa "è"
Monica Heddneck

Risposte:


145

L'oggetto dtype proviene da NumPy, descrive il tipo di elemento in un ndarray. Ogni elemento in un ndarray deve avere la stessa dimensione in byte. Per int64 e float64, sono 8 byte. Ma per le stringhe, la lunghezza della stringa non è fissa. Quindi, invece di salvare direttamente i byte delle stringhe nel ndarray, i Panda usano object ndarray, che salva i puntatori agli oggetti, per questo motivo il dtype di questo tipo ndarray è object.

Ecco un esempio:

  • l'array int64 contiene 4 valori int64.
  • l'array di oggetti contiene 4 puntatori a 3 oggetti stringa.

inserisci qui la descrizione dell'immagine


3
Si noti tuttavia che avere colonne di tipo "oggetto" ha un impatto importante sulle prestazioni delle operazioni di lettura / scrittura di
DataFrame

posso ottenere il tipo di dati restituito come stringa, in qualche modo. So di poter sempre usare il tipo (df ["column"]. Iloc [0]), ma può succedere che sia nan
user1953366

7

La risposta accettata è buona. Volevo solo fornire una risposta che facesse riferimento alla documentazione . La documentazione dice:

Pandas usa l'oggetto dtype per memorizzare le stringhe.

Come dice il commento principale "Non preoccuparti, dovrebbe essere così". (Sebbene la risposta accettata abbia fatto un ottimo lavoro spiegando il "perché"; le stringhe sono di lunghezza variabile)

Ma per le stringhe, la lunghezza della stringa non è fissa.


Perché devo convertire ogni colonna che passo in scipy o sklearn astype (str) per accettarla? sembra che dovrei essere in grado di applicarlo a tutte le colonne inizialmente.
Tinkinc

Non capisco; @Tinkinc cosa succede se non converti le colonne in stringhe? E questa risposta sembra un modo elegante per convertire tutte le colonne,astype(str) anche se mi chiedo ancora che la conversione delle stringhe sia necessaria
The Red Pea

Non riesco a riempire (0) tutti gli oggetti nel mio dataframe rimangono (1, nan) invece di (1,0)
Tinkinc

Mi dispiace @Tinkinc ancora non capisco; Voglio aiutarti, ma il tuo problema sembra più complesso di un commento di Stack Overflow. Considera l'idea di fare una domanda o di unirti a me in chat. (ti ha appena invitato)
The Red Pea

5

La risposta di @ HYRY è fantastica. Voglio solo fornire un po 'più di contesto ..

Matrici memorizzati dati contigui , di dimensioni fisse blocchi di memoria. La combinazione di queste proprietà insieme è ciò che rende gli array velocissimi per l'accesso ai dati. Ad esempio, considerare come il computer potrebbe memorizzare un array di interi a 32 bit, [3,0,1].

inserisci qui la descrizione dell'immagine

Se chiedi al tuo computer di recuperare il terzo elemento dell'array, inizierà dall'inizio e poi salterà su 64 bit per arrivare al terzo elemento. Sapere esattamente quanti bit saltare è ciò che rende veloci gli array .

Consideriamo ora la sequenza di stringhe ['hello', 'i', 'am', 'a', 'banana']. Le stringhe sono oggetti di dimensioni variabili, quindi se provassi a memorizzarli in blocchi di memoria contigui, finirebbe per assomigliare a questo.

inserisci qui la descrizione dell'immagine

Ora il tuo computer non ha un modo veloce per accedere a un elemento richiesto a caso. La chiave per superare questo problema è usare i puntatori. Fondamentalmente, memorizza ogni stringa in una posizione di memoria casuale e riempi l'array con l'indirizzo di memoria di ciascuna stringa. (Gli indirizzi di memoria sono solo numeri interi.) Quindi ora le cose sembrano così

inserisci qui la descrizione dell'immagine

Ora, se chiedi al tuo computer di recuperare il terzo elemento, proprio come prima, può saltare su 64 bit (supponendo che gli indirizzi di memoria siano interi a 32 bit) e quindi fare un passaggio aggiuntivo per andare a prendere la stringa.

La sfida per NumPy è che non c'è alcuna garanzia che i puntatori puntino effettivamente alle stringhe. Ecco perché riporta il dtype come "oggetto".

Spudoratamente inserirò il mio articolo sul blog in cui ne avevo discusso originariamente.


Ben scritto
..

1

A partire dalla versione 1.0.0 (gennaio 2020), panda ha introdotto come funzionalità sperimentale che fornisce un supporto di prima classe per i tipi di stringa pandas.StringDtype.

Mentre ci si può comunque essere visto objectper impostazione predefinita, il nuovo tipo può essere utilizzato specificando una dtypedelle pd.StringDtypeo semplicemente 'string':

>>> pd.Series(['abc', None, 'def'])
0     abc
1    None
2     def
dtype: object
>>> pd.Series(['abc', None, 'def'], dtype=pd.StringDtype())
0     abc
1    <NA>
2     def
dtype: string
>>> pd.Series(['abc', None, 'def']).astype('string')
0     abc
1    <NA>
2     def
dtype: string

2
Non usare questo .... ancora. Come hanno affermato, il The implementation may change without warning.che significa che i nuovi aggiornamenti interromperanno i vecchi programmi.
NoName

1
Bene, tutto dipende da cosa lo userai. Se si desidera utilizzarlo in un sistema di produzione in cui sono necessari aggiornamenti continui dei pacchetti e in cui la rottura dell'API causa un carico di manutenzione inaccettabile, allora certo, prestare molta attenzione alla parola "sperimentale", ma se si utilizzano i panda per eseguire operazioni esplorative analisi in copioni la cui durata non aumenta una giornata lavorativa, quindi queste preoccupazioni dovrebbero significare poco per te.
fuglede

A partire da Pandas 1.1, l'API sembra essere stabilizzata Tutti i dtypes possono ora essere convertiti in StringDtype .
D3f0
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.