dtype
konvertieren¶
Manchmal passen die pandas-Datentypen nicht wirklich gut. Dies kann z.B. auf Serialisierungsformate zurückzuführen sein, die keine Typinformationen enthalten. Manchmal solltet ihr jedoch den Typ auch ändern, um eine bessere Performance zu erzielen – entweder mehr Manipulationsmöglichkeiten oder weniger Speicherbedarf. In den folgenden Beispielen werden wir verschiedene Konvertierungen einer Series
vornehmen:
[1]:
import numpy as np
import pandas as pd
[2]:
s = pd.Series(np.random.randn(7))
[3]:
s
[3]:
0 -0.540728
1 -1.803588
2 2.709375
3 0.020922
4 -1.233492
5 1.809115
6 -1.310579
dtype: float64
Automatische Konvertierung¶
pandas.Series.convert_dtypes versucht, eine Series
in einen Typ zu konvertieren, der NA
unterstützt. Im Fall unserer Series
wird der Typ von float64
in Float64
geändert:
[4]:
s.convert_dtypes()
[4]:
0 -0.540728
1 -1.803588
2 2.709375
3 0.020922
4 -1.233492
5 1.809115
6 -1.310579
dtype: Float64
Bedauerlicherweise habe ich jedoch mit convert_dtypes
kaum Kontrolle darüber, in welchen Datentyp konvertiert wird. Daher bevorzuge ich pandas.Series.astype:
[5]:
s.astype("Float32")
[5]:
0 -0.540728
1 -1.803589
2 2.709375
3 0.020922
4 -1.233492
5 1.809115
6 -1.310579
dtype: Float32
Die Verwendung des richtigen Typs kann Speicherplatz einsparen. Üblich ist ein 8 Byte breiter Datentyp, also int64
oder float64
. Wenn ihr einen schmaleren Typ verwenden könnt, reduziert dies den Speicherverbrauch deutlich, sodass ihr mehr Daten verarbeiten könnt. Ihr könnt NumPy verwenden, um die Grenzen von Integer- und Float-Typen zu überprüfen:
[6]:
np.iinfo("int64")
[6]:
iinfo(min=-9223372036854775808, max=9223372036854775807, dtype=int64)
[7]:
np.finfo("float32")
[7]:
finfo(resolution=1e-06, min=-3.4028235e+38, max=3.4028235e+38, dtype=float32)
[8]:
np.finfo('float64')
[8]:
finfo(resolution=1e-15, min=-1.7976931348623157e+308, max=1.7976931348623157e+308, dtype=float64)
Speicherverbrauch¶
Um den Speicherverbrauch der Series
zu berechnen, könnt ihr pandas.Series.nbytes verwenden um den Speicher, der von den Daten verwendet wird, zu ermitteln. pandas.Series.memory_usage erfasst darüberhinaus auch den Indexspeicher und den Datentyp. Mit deep=True
lässt sich auch der Speicherverbrauch auf Systemebene ermitteln.
[9]:
s.nbytes
[9]:
56
[10]:
s.astype("Float32").nbytes
[10]:
35
[11]:
s.memory_usage()
[11]:
188
[12]:
s.astype("Float32").memory_usage()
[12]:
167
[13]:
s.memory_usage(deep=True)
[13]:
188
String- und Kategorietypen¶
Die Methode pandas.Series.astype kann auch numerische Reihen in Zeichenketten umwandeln, wenn ihr str
übergebt. Beachtet den dtype
im folgenden Beispiel:
[14]:
s.astype(str)
[14]:
0 -0.5407280521417943
1 -1.8035884918817433
2 2.709375360462432
3 0.020922480171874997
4 -1.2334923058043816
5 1.809115347105466
6 -1.3105793583289318
dtype: object
[15]:
s.astype(str).memory_usage()
[15]:
188
[16]:
s.astype(str).memory_usage(deep=True)
[16]:
661
Zur Konvertierung in einen kategorialen Typ könnt ihr 'category'
als Typ übergeben:
[17]:
s.astype(str).astype("category")
[17]:
0 -0.5407280521417943
1 -1.8035884918817433
2 2.709375360462432
3 0.020922480171874997
4 -1.2334923058043816
5 1.809115347105466
6 -1.3105793583289318
dtype: category
Categories (7, object): ['-0.5407280521417943', '-1.2334923058043816', '-1.3105793583289318', '-1.8035884918817433', '0.020922480171874997', '1.809115347105466', '2.709375360462432']
Eine kategoriale Series
ist nützlich für String-Daten und kann zu großen Speichereinsparungen führen. Das liegt daran, dass pandas bei der Konvertierung in kategoriale Daten nicht länger Python-Strings für jeden Wert verwendet, sondern sich wiederholende Werte nicht dupliziert werden. Ihr habt immer noch alle Funktionen des str
-Attributs, aber ihr spart viel Speicherplatz wenn ihr viele doppelte Werte habt und steigert die Leistung, da ihr nicht so viele String-Operationen durchführen
müsst.
[18]:
s.astype("category").memory_usage(deep=True)
[18]:
495
Geordnete Kategorien¶
Um geordnete Kategorien zu erstellen, müsst ihr einen eigenen pandas.CategoricalDtype definieren:
[19]:
from pandas.api.types import CategoricalDtype
sorted = pd.Series(sorted(set(s)))
cat_dtype = CategoricalDtype(categories=sorted, ordered=True)
s.astype(cat_dtype)
[19]:
0 -0.540728
1 -1.803588
2 2.709375
3 0.020922
4 -1.233492
5 1.809115
6 -1.310579
dtype: category
Categories (7, float64): [-1.803588 < -1.310579 < -1.233492 < -0.540728 < 0.020922 < 1.809115 < 2.709375]
[20]:
s.astype(cat_dtype).memory_usage(deep=True)
[20]:
495
In der folgenden Tabelle sind die Typen aufgeführt, die ihr an astype
übergeben könnt.
Datentyp |
Beschreibung |
---|---|
|
in Python-String konvertieren |
|
in Pandas-String konvertieren mit |
|
in NumPy |
|
in NumPy |
|
in pandas |
|
in Floats konvertieren |
|
in |
Umwandlung in andere Datentypen¶
Die Methode pandas.Series.to_numpy oder die Eigenschaft pandas.Series.values liefert uns ein NumPy-Array mit Werten, und pandas.Series.to_list gibt eine Python-Liste mit Werten zurück. Warum solltet ihr das wollen? pandas-Objekte sind meist viel benutzerfreundlicher und der Code lässt sich leichter lesen. Zudem werden Python-Listen sehr viel langsamer verarbeitet werden können. Mit pandas.Series.to_frame könnt ihr ggf. einen DataFrame mit einer einzigen Spalte erzeugen:
[21]:
s.to_frame()
[21]:
0 | |
---|---|
0 | -0.540728 |
1 | -1.803588 |
2 | 2.709375 |
3 | 0.020922 |
4 | -1.233492 |
5 | 1.809115 |
6 | -1.310579 |
Auch die Funktion pandas.to_datetime kann hilfreich sein um in pandas um Werte in Datum und Uhrzeit zu konvertieren.