it-swarm.com.de

Ändern Sie den Datentyp der Spalten in Pandas

Ich möchte eine Tabelle, die als Liste von Listen dargestellt wird, in einen Pandas DataFrame konvertieren. Als extrem vereinfachtes Beispiel:

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

Wie konvertiere ich die Spalten am besten in die entsprechenden Typen, in diesem Fall die Spalten 2 und 3 in Floats? Gibt es eine Möglichkeit, die Typen bei der Konvertierung in DataFrame anzugeben? Oder ist es besser, zuerst den DataFrame zu erstellen und dann die Spalten zu durchlaufen, um den Typ für jede Spalte zu ändern? Idealerweise würde ich das gerne dynamisch tun, da es hunderte von Spalten geben kann und ich nicht genau angeben möchte, welche Spalten welchen Typs sind. Ich kann nur garantieren, dass jede Spalte Werte des gleichen Typs enthält.

507
user1642513

Sie haben drei Hauptoptionen zum Konvertieren von Typen in Pandas:

  1. to_numeric() - Bietet Funktionen zum sicheren Konvertieren nicht numerischer Typen (z. B. Zeichenfolgen) in einen geeigneten numerischen Typ. (Siehe auch to_datetime() und to_timedelta() .)

  2. astype() - konvertiere (fast) jeden Typ in (fast) jeden anderen Typ (auch wenn das nicht unbedingt sinnvoll ist). Ermöglicht auch das Konvertieren in kategorial Typen (sehr nützlich).

  3. infer_objects() - eine Dienstprogrammmethode zum Konvertieren von Objektspalten, die Python Objekte enthalten, in einen pandas Typ, wenn möglich.

Lesen Sie weiter, um detailliertere Erklärungen und die Verwendung dieser Methoden zu erhalten.


1. to_numeric()

Am besten konvertieren Sie eine oder mehrere Spalten eines DataFrames in numerische Werte, indem Sie pandas.to_numeric() verwenden.

Mit dieser Funktion wird versucht, nicht numerische Objekte (z. B. Zeichenfolgen) in Ganzzahlen oder Gleitkommazahlen umzuwandeln.

Grundsätzliche Verwendung

Die Eingabe für to_numeric() ist eine Reihe oder eine einzelne Spalte eines DataFrames.

>>> s = pd.Series(["8", 6, "7.5", 3, "0.9"]) # mixed string and numeric values
>>> s
0      8
1      6
2    7.5
3      3
4    0.9
dtype: object

>>> pd.to_numeric(s) # convert everything to float values
0    8.0
1    6.0
2    7.5
3    3.0
4    0.9
dtype: float64

Wie Sie sehen, wird eine neue Serie zurückgegeben. Denken Sie daran, diese Ausgabe einem Variablen- oder Spaltennamen zuzuweisen, um sie weiterhin zu verwenden:

# convert Series
my_series = pd.to_numeric(my_series)

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

Sie können damit auch mehrere Spalten eines DataFrames mit der apply() -Methode konvertieren:

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

Solange Ihre Werte alle konvertiert werden können, ist das wahrscheinlich alles, was Sie brauchen.

Fehlerbehandlung

Was aber, wenn einige Werte nicht in einen numerischen Typ konvertiert werden können?

to_numeric() akzeptiert auch ein errors - Schlüsselwortargument, mit dem Sie erzwingen können, dass nicht numerische Werte NaN sind, oder Spalten, die diese Werte enthalten, einfach ignorieren.

Hier ist ein Beispiel mit einer Reihe von Zeichenfolgen s mit dem Objekt dtype:

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

Das Standardverhalten ist das Erhöhen, wenn ein Wert nicht konvertiert werden kann. In diesem Fall kann die Zeichenfolge 'pandas' nicht verarbeitet werden:

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

Anstatt zu scheitern, möchten wir, dass 'Pandas' als fehlender/falscher numerischer Wert betrachtet werden. Mit dem Schlüsselwortargument NaN können ungültige Werte wie folgt in errors umgewandelt werden:

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

Die dritte Option für errors besteht darin, die Operation zu ignorieren, wenn ein ungültiger Wert auftritt:

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

Diese letzte Option ist besonders nützlich, wenn Sie Ihren gesamten DataFrame konvertieren möchten, aber nicht wissen, welche unserer Spalten zuverlässig in einen numerischen Typ konvertiert werden können. In diesem Fall schreiben Sie einfach:

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

Die Funktion wird auf jede Spalte des DataFrames angewendet. Spalten, die in einen numerischen Typ konvertiert werden können, werden konvertiert, während Spalten, die nicht konvertiert werden können (z. B. Zeichenfolgen oder Datumsangaben, die keine Ziffern enthalten), in Ruhe gelassen werden.

Downcasting

Standardmäßig erhalten Sie bei der Konvertierung mit to_numeric() entweder einen D-Typ int64 Oder float64 (Oder eine ganzzahlige Breite, die für Ihre Plattform typisch ist).

Das ist normalerweise das, was Sie wollen, aber was, wenn Sie etwas Speicher sparen und einen kompakteren D-Typ wie float32 Oder int8 Verwenden möchten?

to_numeric() gibt Ihnen die Möglichkeit, einen Downcast auf 'Integer', 'Signed', 'Unsigned' oder 'Float' durchzuführen. Hier ist ein Beispiel für eine einfache Reihe s vom Typ Integer:

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

Beim Downcasting auf "Ganzzahl" wird die kleinstmögliche Ganzzahl verwendet, die die folgenden Werte enthalten kann:

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

Beim Downcasting zum 'Floaten' wird auf ähnliche Weise ein kleinerer als der normale Floating-Typ ausgewählt:

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

2. astype()

Mit der astype() -Methode können Sie explizit angeben, welchen D-Typ Ihr ​​DataFrame oder Ihre Serie haben soll. Es ist sehr vielseitig, da Sie versuchen können, von einem Typ zum anderen zu wechseln.

Grundsätzliche Verwendung

Wählen Sie einfach einen Typ aus: Sie können einen NumPy-D-Typ (z. B. np.int16), Einige Python Typen (z. B. bool) oder pandaspezifische Typen (wie den kategorialen D-Typ) verwenden.

Rufen Sie die Methode für das Objekt auf, das Sie konvertieren möchten, und astype() wird versuchen, sie für Sie zu konvertieren:

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

Beachten Sie, dass ich "try" gesagt habe - wenn astype() nicht weiß, wie ein Wert in der Serie oder im DataFrame konvertiert wird, wird ein Fehler ausgelöst. Wenn Sie beispielsweise einen Wert für NaN oder inf haben, wird beim Versuch, ihn in eine Ganzzahl umzuwandeln, eine Fehlermeldung angezeigt.

Ab pandas 0.20.0) kann dieser Fehler durch Übergabe von errors='ignore' Unterdrückt werden. Ihr ursprüngliches Objekt wird unberührt zurückgegeben.

Achtung

astype() ist mächtig, konvertiert aber manchmal Werte "falsch". Zum Beispiel:

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

Dies sind kleine Ganzzahlen. Wie wäre es also mit der Konvertierung in einen 8-Bit-Typ ohne Vorzeichen, um Speicherplatz zu sparen?

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

Die Umwandlung funktionierte, aber die -7 wurde auf 249 (d. H. 2) umbrochen8 - 7)!

Der Versuch, mit pd.to_numeric(s, downcast='unsigned') einen Downcast durchzuführen, kann diesen Fehler verhindern.


3. infer_objects()

In Version 0.21.0 von pandas) wurde die Methode infer_objects() zum Konvertieren von Spalten eines DataFrame mit einem Objektdatentyp in einen spezifischeren Typ (soft) eingeführt Umbauten).

Hier ist beispielsweise ein DataFrame mit zwei Spalten des Objekttyps. Einer enthält tatsächliche Ganzzahlen und der andere enthält Zeichenfolgen, die Ganzzahlen darstellen:

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

Mit infer_objects() können Sie den Spaltentyp 'a' in int64 ändern:

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

Die Spalte 'b' wurde alleine gelassen, da es sich bei den Werten um Zeichenfolgen und nicht um Ganzzahlen handelte. Wenn Sie versuchen möchten, die Konvertierung beider Spalten in einen Integer-Typ zu erzwingen, können Sie stattdessen df.astype(int) verwenden.

875
Alex Riley

Wie wäre es damit? 

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
411
hernamesbarbara

dieser Code ändert den Datentyp der Spalte.

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

anstelle des Datentyps können Sie Ihrem Datentyp .Was möchten Sie wie Str, Float, Int usw.

28
Akash Nayak

Hier ist eine Funktion, die als Argument einen DataFrame und eine Liste von Spalten verwendet und alle Daten in den Spalten in Zahlen umwandelt.

# df is the DataFrame, and column_list is a list of columns as strings (e.g ["col1","col2","col3"])
# dependencies: pandas

def coerce_df_columns_to_numeric(df, column_list):
    df[column_list] = df[column_list].apply(pd.to_numeric, errors='coerce')

Also für dein Beispiel:

import pandas as pd

def coerce_df_columns_to_numeric(df, column_list):
    df[column_list] = df[column_list].apply(pd.to_numeric, errors='coerce')

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

coerce_df_columns_to_numeric(df, ['col2','col3'])
12
Harry Stevens

Wie wäre es, zwei Datenrahmen mit jeweils unterschiedlichen Datentypen für ihre Spalten zu erstellen und diese dann zusammenzufügen?

d1 = pd.DataFrame(columns=[ 'float_column' ], dtype=float)
d1 = d1.append(pd.DataFrame(columns=[ 'string_column' ], dtype=str))

Ergebnisse

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

Nach der Erstellung des Datenrahmens können Sie in der 1. Spalte Fließkomma-Variablen und in der 2. Spalte Zeichenfolgen (oder einen beliebigen Datentyp) angeben. 

6
MikeyE

Wenn ich nur bestimmte Spalten angeben musste und explizit sein möchte, habe ich (per DOCS LOCATION ) Folgendes verwendet:

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

Also, die ursprüngliche Frage verwenden, aber Spaltennamen angeben ...

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'})
2
Thom Ives

Ich dachte, ich hätte das gleiche Problem, aber tatsächlich habe ich einen kleinen Unterschied, der das Problem leichter zu lösen macht. Für andere, die sich diese Frage ansehen, sollten Sie das Format Ihrer Eingabeliste überprüfen. In meinem Fall handelt es sich bei den Zahlen zunächst um Floats und nicht um Strings wie in der Frage:

a = [['a', 1.2, 4.2], ['b', 70, 0.03], ['x', 5, 0]]

durch die Verarbeitung der Liste zu viel vor dem Erstellen des Datenrahmens verliere ich die Typen und alles wird zu einem String. 

Erstellen des Datenrahmens über ein numpy-Array

df = pd.DataFrame(np.array(a))

df
Out[5]: 
   0    1     2
0  a  1.2   4.2
1  b   70  0.03
2  x    5     0

df[1].dtype
Out[7]: dtype('O')

gibt den gleichen Datenrahmen wie in der Frage an, wobei die Einträge in den Spalten 1 und 2 als Zeichenfolgen betrachtet werden. Jedoch tun

df = pd.DataFrame(a)

df
Out[10]: 
   0     1     2
0  a   1.2  4.20
1  b  70.0  0.03
2  x   5.0  0.00

df[1].dtype
Out[11]: dtype('float64')

gibt tatsächlich einen Datenrahmen mit den Spalten im richtigen Format

0
SarahD