Zeichenfolgen in einem DataFrame, aber dtype ist ein Objekt

96

Warum sagt mir Pandas, dass ich Objekte habe, obwohl jedes Element in der ausgewählten Spalte eine Zeichenfolge ist - auch nach expliziter Konvertierung.

Dies ist mein 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)

Fünf von ihnen sind dtype object. Ich konvertiere diese Objekte explizit in Zeichenfolgen:

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

Dann hat df["attr2"]noch dtype object, obwohl type(df["attr2"].ix[0]offenbart str, was richtig ist.

Pandas unterscheidet zwischen int64und float64und object. Was ist die Logik dahinter, wenn es keine gibt dtype str? Warum ist ein strabgedeckt von object?

Xiphias
quelle
Kam hierher, weil
Verknüpfungen

Antworten:

145

Das dtype-Objekt stammt von NumPy und beschreibt den Elementtyp in einem ndarray. Jedes Element in einem ndarray muss dieselbe Byte-Größe haben. Für int64 und float64 sind dies 8 Bytes. Bei Zeichenfolgen ist die Länge der Zeichenfolge jedoch nicht festgelegt. Anstatt die Bytes der Zeichenfolgen direkt im ndarray zu speichern, verwenden Pandas das Objekt ndarray, das Zeiger auf Objekte speichert. Aus diesem Grund ist der dtype dieser Art ndarray object.

Hier ist ein Beispiel:

  • Das int64-Array enthält 4 int64-Werte.
  • Das Objektarray enthält 4 Zeiger auf 3 Zeichenfolgenobjekte.

Geben Sie hier die Bildbeschreibung ein

HYRY
quelle
3
Beachten Sie jedoch, dass Spalten vom Typ 'Objekt' einen großen Einfluss auf die Leistung der Lese- / Schreibvorgänge von DataFrame haben
Erwanp
Kann ich den Datentyp irgendwie als Zeichenfolge zurückgeben lassen? Ich weiß, dass ich immer type (df ["column"]. Iloc [0]) verwenden kann, aber es kann vorkommen, dass es nan
user1953366
7

Die akzeptierte Antwort ist gut. Ich wollte nur eine Antwort geben, die auf die Dokumentation verweist . Die Dokumentation sagt:

Pandas verwendet den Objekttyp zum Speichern von Zeichenfolgen.

Wie der Hauptkommentar sagt: "Mach dir keine Sorgen, es soll so sein." (Obwohl die akzeptierte Antwort großartige Arbeit geleistet hat, um das "Warum" zu erklären; Zeichenfolgen sind variabel lang)

Bei Zeichenfolgen ist die Länge der Zeichenfolge jedoch nicht festgelegt.

Die rote Erbse
quelle
Warum muss ich jede Spalte, die ich übergebe, in scipy oder sklearn astype (str) konvertieren, damit sie akzeptiert wird? Anscheinend sollte ich das zunächst auf alle Spalten anwenden können.
Tinkinc
Ich verstehe nicht; @Tinkinc , was passiert , wenn Sie nicht Spalten Zeichenfolge konvertieren? Und diese Antwort scheint eine elegante Möglichkeit zu sein, alle Spalten zu konvertieren,astype(str) obwohl ich mich immer noch fragen würde , ob eine Konvertierung von Zeichenfolgen erforderlich ist
The Red Pea
Ich kann nicht füllen (0) alle Objekte in meinem Datenrahmen bleiben (1, nan) statt (1,0)
Tinkinc
Sorry @Tinkinc Ich verstehe immer noch nicht; Ich möchte helfen, aber Ihr Problem klingt komplexer als ein Kommentar zum Stapelüberlauf. Stellen Sie eine Frage oder nehmen Sie an einem Chat teil. (gerade eingeladen)
Die rote Erbse
5

@ HYRYs Antwort ist großartig. Ich möchte nur etwas mehr Kontext bereitstellen.

Arrays gespeicherten Daten als zusammenhängende , feste Größe Speicherblocks. Die Kombination dieser Eigenschaften macht Arrays blitzschnell für den Datenzugriff. Überlegen Sie beispielsweise, wie Ihr Computer ein Array von 32-Bit-Ganzzahlen speichern könnte [3,0,1].

Geben Sie hier die Bildbeschreibung ein

Wenn Sie Ihren Computer bitten, das dritte Element im Array abzurufen, beginnt es am Anfang und springt dann über 64 Bit, um zum dritten Element zu gelangen. Wenn Sie genau wissen, über wie viele Bits Sie springen müssen, sind Arrays schnell .

Betrachten Sie nun die Reihenfolge der Zeichenfolgen ['hello', 'i', 'am', 'a', 'banana']. Strings sind Objekte mit unterschiedlicher Größe. Wenn Sie also versuchen, sie in zusammenhängenden Speicherblöcken zu speichern, sieht sie am Ende so aus.

Geben Sie hier die Bildbeschreibung ein

Jetzt hat Ihr Computer keine schnelle Möglichkeit, auf ein zufällig angefordertes Element zuzugreifen. Der Schlüssel zur Überwindung dieses Problems ist die Verwendung von Zeigern. Speichern Sie grundsätzlich jede Zeichenfolge an einem zufälligen Speicherort und füllen Sie das Array mit der Speicheradresse jeder Zeichenfolge. (Speicheradressen sind nur ganze Zahlen.) Nun sehen die Dinge so aus

Geben Sie hier die Bildbeschreibung ein

Wenn Sie Ihren Computer nun wie zuvor auffordern, das dritte Element abzurufen, kann er über 64 Bit springen (vorausgesetzt, die Speicheradressen sind 32-Bit-Ganzzahlen), und dann einen zusätzlichen Schritt ausführen, um die Zeichenfolge abzurufen.

Die Herausforderung für NumPy besteht darin, dass es keine Garantie gibt, dass die Zeiger tatsächlich auf Zeichenfolgen zeigen. Aus diesem Grund wird der dtype als "Objekt" gemeldet.

Ich werde schamlos meinen eigenen Blog-Artikel einstecken, in dem ich das ursprünglich besprochen habe.

Ben
quelle
Schön geschrieben. Danke
Tedd
1

Ab Version 1.0.0 (Januar 2020) hat pandas eine experimentelle Funktion eingeführt, die erstklassige Unterstützung für String-Typen bietet pandas.StringDtype.

Während Sie objectstandardmäßig immer noch sehen , kann der neue Typ verwendet werden, indem Sie ein dtypevon pd.StringDtypeoder einfach Folgendes angeben '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
Fuglede
quelle
2
Benutze das noch nicht. Wie bereits erwähnt, The implementation may change without warning.bedeutet dies, dass neue Updates Ihre alten Programme beschädigen.
NoName
1
Nun, das hängt alles davon ab, wofür Sie es verwenden werden. Wenn Sie es in einem Produktionssystem verwenden möchten, in dem kontinuierliche Paketaktualisierungen erforderlich sind und bei dem API-Brüche eine inakzeptable Wartungsbelastung verursachen, achten Sie auf das Wort "experimentell". Wenn Sie jedoch Pandas verwenden, um Erkundungen durchzuführen Analysen in Skripten, deren Lebensdauer einen Arbeitstag nicht verlängert, sollten Ihnen diese Bedenken wenig bedeuten.
Fuglede