Le titre de la question posée est général, mais le cas d'utilisation des auteurs indiqué dans le corps de la question est spécifique. Donc, toutes les autres réponses peuvent être utilisées.
Mais pour répondre pleinement à la question du titre, il convient de préciser qu'il semble que toutes les approches peuvent échouer dans certains cas et nécessiter quelques retouches. Je les ai tous examinés (et certains supplémentaires) par ordre décroissant de fiabilité (à mon avis):
1. Comparaison des types directement via ==
(réponse acceptée).
Malgré le fait que cette réponse est acceptée et que la plupart des votes positifs comptent, je pense que cette méthode ne devrait pas du tout être utilisée. Car en fait cette approche est déconseillée en python comme mentionné à plusieurs reprises ici .
Mais si l' on veut encore utiliser - devrait être au courant de certains comme dtypes pandas géants-spécifiques de pd.CategoricalDType
, pd.PeriodDtype
ou pd.IntervalDtype
. Ici, il faut utiliser un supplément type( )
pour reconnaître correctement dtype:
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
Une autre mise en garde ici est que ce type doit être souligné avec précision:
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()
approche.
Cette méthode n'a pas encore été mentionnée dans les réponses.
Donc, si la comparaison directe des types n'est pas une bonne idée - essayons la fonction python intégrée à cet effet, à savoir - isinstance()
.
Cela échoue juste au début, car suppose que nous avons des objets, mais pd.Series
ou pd.DataFrame
peuvent être utilisés comme de simples conteneurs vides avec des dtype
objets prédéfinis mais pas d'objets:
s = pd.Series([], dtype=bool)
s
>>> Series([], dtype: bool)
Mais si l'on surmonte ce problème d'une manière ou d'une autre, et veut accéder à chaque objet, par exemple, dans la première ligne et vérifie son dtype comme quelque chose comme ça:
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')
Ce sera trompeur dans le cas de type mixte de données dans une seule colonne:
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')
Et le dernier mais non le moindre - cette méthode ne peut pas reconnaître directement Category
dtype. Comme indiqué dans la documentation :
Le renvoi d'un seul élément à partir de données catégorielles renverra également la valeur, et non une catégorie de longueur «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')
Donc, cette méthode est également presque inapplicable.
3. df.dtype.kind
approche.
Cette méthode peut encore fonctionner avec vide pd.Series
ou pd.DataFrames
mais présente d'autres problèmes.
Premièrement, il est impossible de différer certains types de dtypes:
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
Deuxièmement, ce qui n'est pas encore clair pour moi, il revient même sur certains dtypes Aucun .
4. df.select_dtypes
approche.
C'est presque ce que nous voulons. Cette méthode est conçue à l'intérieur des pandas afin de gérer la plupart des cas de coin mentionnés précédemment - les DataFrames vides, diffère bien des dtypes numpy ou spécifiques aux pandas. Cela fonctionne bien avec un seul dtype comme .select_dtypes('bool')
. Il peut être utilisé même pour sélectionner des groupes de colonnes en fonction de dtype:
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')
Comme tel, comme indiqué dans la documentation :
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
On peut penser que nous voyons ici les premiers résultats inattendus (auparavant pour moi: question ) - TimeDelta
est inclus dans la sortie DataFrame
. Mais comme il a répondu au contraire, il devrait en être ainsi, mais il faut en être conscient. Notez que bool
dtype est ignoré, ce qui peut également être indésirable pour quelqu'un, mais cela est dû à bool
et se number
trouve dans différents " sous-arbres " de dtypes numpy. Dans le cas de bool, nous pouvons utiliser test.select_dtypes(['bool'])
ici.
La prochaine restriction de cette méthode est que pour la version actuelle de pandas (0.24.2), ce code: test.select_dtypes('period')
augmentera NotImplementedError
.
Et une autre chose est qu'il ne peut pas différer les chaînes des autres objets:
test.select_dtypes('object')
>>> str obj
>>> 0 s1 [1, 2, 3]
>>> 1 s2 [5435, 35, -52, 14]
Mais c'est, d'abord - déjà mentionné dans la documentation. Et deuxièmement, ce n'est pas le problème de cette méthode, mais plutôt la façon dont les chaînes sont stockées DataFrame
. Mais de toute façon, ce cas doit avoir un post-traitement.
5. df.api.types.is_XXX_dtype
approche.
Celui-ci est destiné à être le moyen le plus robuste et le plus natif de réaliser la reconnaissance de type dtype (chemin du module où les fonctions résident dit par lui-même) comme je suppose. Et cela fonctionne presque parfaitement, mais il reste au moins une mise en garde et doit encore distinguer les colonnes de chaînes .
En outre, cela peut être subjectif, mais cette approche a également un number
traitement de groupe dtypes plus `` compréhensible par l' homme '' par rapport à .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
Non timedelta
et bool
est inclus. Parfait.
Mon pipeline exploite exactement cette fonctionnalité à ce moment, plus un peu de traitement post-manuel.
Production.
J'espère avoir pu argumenter le point principal - que toutes les approches discutées peuvent être utilisées, mais seulement pd.DataFrame.select_dtypes()
et pd.api.types.is_XXX_dtype
devraient être vraiment considérées comme les approches applicables.
string
n'est pas un dtype