Der Titel der gestellten Frage ist allgemein, aber der im Hauptteil der Frage angegebene Anwendungsfall der Autoren ist spezifisch. Es können also auch andere Antworten verwendet werden.
Aber um in vollem Umfang die Antwort Titelfrage sollte klargestellt werden , dass es scheint , als ob alle Ansätze können nicht in einigen Fällen und einig Nacharbeit erfordern. Ich habe alle (und einige zusätzliche) in abnehmender Reihenfolge der Zuverlässigkeit überprüft (meiner Meinung nach):
1. Typen direkt über vergleichen ==
(akzeptierte Antwort).
Trotz der Tatsache, dass dies eine akzeptierte Antwort ist und die meisten Upvotes zählen, denke ich, dass diese Methode überhaupt nicht angewendet werden sollte. Weil in der Tat von diesem Ansatz in Python abgeraten wird, wie hier mehrmals erwähnt .
Aber wenn man sich noch verwenden mag - soll wie von einigen Pandas spezifischen dtypes darüber im Klaren sein pd.CategoricalDType
, pd.PeriodDtype
oder pd.IntervalDtype
. Hier muss man extra type( )
verwenden, um dtype richtig zu erkennen:
s = pd.Series([pd.Period('2002-03','D'), pd.Period('2012-02-01', 'D')])
s
s.dtype == pd.PeriodDtype # Not working
type(s.dtype) == pd.PeriodDtype # working
>>> 0 2002-03-01
>>> 1 2012-02-01
>>> dtype: period[D]
>>> False
>>> True
Eine weitere Einschränkung ist, dass der Typ genau hervorgehoben werden sollte:
s = pd.Series([1,2])
s
s.dtype == np.int64 # Working
s.dtype == np.int32 # Not working
>>> 0 1
>>> 1 2
>>> dtype: int64
>>> True
>>> False
2. isinstance()
Ansatz.
Diese Methode wurde bisher in den Antworten nicht erwähnt.
Wenn ein direkter Vergleich von Typen keine gute Idee ist, können Sie zu diesem Zweck die integrierte Python-Funktion ausprobieren, nämlich - isinstance()
.
Es schlägt nur am Anfang fehl, da davon ausgegangen wird, dass wir einige Objekte haben, aber pd.Series
oder pd.DataFrame
nur als leere Container mit vordefinierten, dtype
aber keinen Objekten darin verwendet werden können:
s = pd.Series([], dtype=bool)
s
>>> Series([], dtype: bool)
Aber wenn man dieses Problem irgendwie überwindet und auf jedes Objekt zugreifen möchte, zum Beispiel in der ersten Zeile, und seinen dtype wie folgt überprüft:
df = pd.DataFrame({'int': [12, 2], 'dt': [pd.Timestamp('2013-01-02'), pd.Timestamp('2016-10-20')]},
index = ['A', 'B'])
for col in df.columns:
df[col].dtype, 'is_int64 = %s' % isinstance(df.loc['A', col], np.int64)
>>> (dtype('int64'), 'is_int64 = True')
>>> (dtype('<M8[ns]'), 'is_int64 = False')
Bei gemischten Datentypen in einer Spalte ist dies irreführend:
df2 = pd.DataFrame({'data': [12, pd.Timestamp('2013-01-02')]},
index = ['A', 'B'])
for col in df2.columns:
df2[col].dtype, 'is_int64 = %s' % isinstance(df2.loc['A', col], np.int64)
>>> (dtype('O'), 'is_int64 = False')
Und last but not least - diese Methode kann Category
dtype nicht direkt erkennen . Wie in den Dokumenten angegeben :
Wenn Sie ein einzelnes Element aus kategorialen Daten zurückgeben, wird auch der Wert zurückgegeben, nicht eine Kategorie mit der Länge „1“.
df['int'] = df['int'].astype('category')
for col in df.columns:
df[col].dtype, 'is_int64 = %s' % isinstance(df.loc['A', col], np.int64)
>>> (CategoricalDtype(categories=[2, 12], ordered=False), 'is_int64 = True')
>>> (dtype('<M8[ns]'), 'is_int64 = False')
Diese Methode ist also auch fast nicht anwendbar.
3. df.dtype.kind
Ansatz.
Diese Methode funktioniert möglicherweise noch mit leer pd.Series
oder hat pd.DataFrames
aber andere Probleme.
Erstens - es kann einige d-Typen nicht unterscheiden:
df = pd.DataFrame({'prd' :[pd.Period('2002-03','D'), pd.Period('2012-02-01', 'D')],
'str' :['s1', 's2'],
'cat' :[1, -1]})
df['cat'] = df['cat'].astype('category')
for col in df:
# kind will define all columns as 'Object'
print (df[col].dtype, df[col].dtype.kind)
>>> period[D] O
>>> object O
>>> category O
Zweitens, was für mich eigentlich noch unklar ist, gibt es sogar bei einigen dtypes None zurück .
4. df.select_dtypes
Ansatz.
Das ist fast das, was wir wollen. Diese Methode wurde in Pandas entwickelt, um die meisten zuvor erwähnten Eckfälle zu behandeln - leere DataFrames, unterscheidet sich gut von numpy- oder pandas-spezifischen dtypes. Es funktioniert gut mit einzelnen dtype wie .select_dtypes('bool')
. Es kann sogar zum Auswählen von Spaltengruppen basierend auf dtype verwendet werden:
test = pd.DataFrame({'bool' :[False, True], 'int64':[-1,2], 'int32':[-1,2],'float': [-2.5, 3.4],
'compl':np.array([1-1j, 5]),
'dt' :[pd.Timestamp('2013-01-02'), pd.Timestamp('2016-10-20')],
'td' :[pd.Timestamp('2012-03-02')- pd.Timestamp('2016-10-20'),
pd.Timestamp('2010-07-12')- pd.Timestamp('2000-11-10')],
'prd' :[pd.Period('2002-03','D'), pd.Period('2012-02-01', 'D')],
'intrv':pd.arrays.IntervalArray([pd.Interval(0, 0.1), pd.Interval(1, 5)]),
'str' :['s1', 's2'],
'cat' :[1, -1],
'obj' :[[1,2,3], [5435,35,-52,14]]
})
test['int32'] = test['int32'].astype(np.int32)
test['cat'] = test['cat'].astype('category')
Wie in den Dokumenten angegeben :
test.select_dtypes('number')
>>> int64 int32 float compl td
>>> 0 -1 -1 -2.5 (1-1j) -1693 days
>>> 1 2 2 3.4 (5+0j) 3531 days
Man könnte denken, dass wir hier erste unerwartete (für mich früher: Frage ) Ergebnisse sehen - TimeDelta
sind in der Ausgabe enthalten DataFrame
. Aber wie im Gegenteil beantwortet , sollte es so sein, aber man muss sich dessen bewusst sein. Beachten Sie, dass bool
dtype übersprungen wird, was für jemanden möglicherweise auch unerwünscht ist, aber auf verschiedene " Teilbäume " von numpy dtypes zurückzuführen ist bool
und number
sich in diesen befindet. Im Falle von Bool können wir hier verwenden.test.select_dtypes(['bool'])
Die nächste Einschränkung dieser Methode besteht darin, dass für die aktuelle Version von Pandas (0.24.2) dieser Code: ausgelöst test.select_dtypes('period')
wird NotImplementedError
.
Und eine andere Sache ist, dass es nicht möglich ist, Zeichenfolgen von anderen Objekten zu unterscheiden:
test.select_dtypes('object')
>>> str obj
>>> 0 s1 [1, 2, 3]
>>> 1 s2 [5435, 35, -52, 14]
Aber das ist erstens - bereits erwähnt in der Dokumentation. Und zweitens - ist nicht das Problem dieser Methode, sondern die Art und Weise, wie Zeichenfolgen gespeichert werden DataFrame
. Aber trotzdem muss dieser Fall eine Nachbearbeitung haben.
5. df.api.types.is_XXX_dtype
Ansatz.
Dieser soll der robusteste und nativste Weg sein, um eine dtype-Erkennung zu erreichen (der Pfad des Moduls, in dem sich die Funktionen befinden, sagt von selbst), wie ich vermute. Und es funktioniert fast perfekt, hat aber immer noch mindestens eine Einschränkung und muss trotzdem irgendwie String-Spalten unterscheiden .
Außerdem mag dies subjektiv sein, aber dieser Ansatz hat auch eine "vom Menschen verständliche" number
Verarbeitung von dtypes-Gruppen im Vergleich zu .select_dtypes('number')
:
for col in test.columns:
if pd.api.types.is_numeric_dtype(test[col]):
print (test[col].dtype)
>>> bool
>>> int64
>>> int32
>>> float64
>>> complex128
Nein timedelta
und bool
ist enthalten. Perfekt.
Meine Pipeline nutzt zu diesem Zeitpunkt genau diese Funktionalität sowie ein wenig Nachbearbeitung.
Ausgabe.
Ich hoffe, ich konnte den Hauptpunkt argumentieren - dass alle diskutierten Ansätze verwendet werden können, aber nur pd.DataFrame.select_dtypes()
und pd.api.types.is_XXX_dtype
wirklich als die anwendbaren betrachtet werden sollten.
string
ist kein dtype