Назва запитуваного питання загальна, але автори використовують випадок, зазначений в тілі питання, специфічний. Тож будь-які інші відповіді можуть бути використані.
Але для того, щоб повністю відповісти на головне запитання, слід уточнити, що, здається, у всіх випадках всі підходи можуть провалюватися і вимагати певної переробки. Я переглянув усі (та деякі додаткові) в порядку зниження надійності (на мою думку):
1. Порівняння типів безпосередньо через ==
(прийнята відповідь).
Незважаючи на те, що ця відповідь прийнята і має більшу кількість підрахунків, я думаю, що цей метод не слід застосовувати взагалі. Тому що насправді цей підхід НЕ рекомендується в пітона , як згадувалося кілька разів тут .
Але якщо один все ще хочете використовувати його - повинні бути інформовані про деякі панди специфічних dtypes , як pd.CategoricalDType
, pd.PeriodDtype
або pd.IntervalDtype
. Тут потрібно використовувати додаткові type( )
для правильного розпізнавання 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
Ще одне застереження тут полягає в тому, що тип слід точно вказати:
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()
підхід.
Цей метод досі не згадується у відповідях.
Тож якщо пряме порівняння типів не є хорошою ідеєю - давайте спробуємо вбудовану функцію python для цієї мети, а саме - isinstance()
.
Він зазнає невдачі тільки на самому початку, так як передбачається , що у нас є якісь - то об'єкти, але pd.Series
і pd.DataFrame
можуть бути використані як тільки порожні контейнери з зумовлені , dtype
але без будь - яких об'єктів в ньому:
s = pd.Series([], dtype=bool)
s
>>> Series([], dtype: bool)
Але якщо хтось якось подолати це питання і хоче отримати доступ до кожного об'єкта, наприклад, у першому рядку та перевіряє його тип як-небудь подібне:
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')
Це буде вводити в оману у випадку змішаного типу даних в одному стовпчику:
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')
І останнє, але не менш важливе - цей метод не може безпосередньо розпізнати Category
dtype. Як зазначено в документах :
Повернення одного елемента з категоричних даних також поверне значення, а не категоричне довжиною "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')
Тож цей метод також майже не застосовується.
3. df.dtype.kind
підхід.
Цей метод ще може працювати з порожнім pd.Series
або pd.DataFrames
має інші проблеми.
По-перше - він не може відрізняти деякі типи:
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
По-друге, те, що насправді для мене ще незрозуміло, навіть повертається на деякі типи None .
4. df.select_dtypes
підхід.
Це майже те, що ми хочемо. Цей метод, розроблений всередині панд, таким чином обробляє більшість згаданих раніше кутових випадків - порожні DataFrames, добре відрізняються нумеровані або панд-типові типи. Він добре працює з одним типом типу .select_dtypes('bool')
. Він може бути використаний навіть для вибору груп стовпців на основі 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')
Так, як зазначено в документах :
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
Подальше може подумати, що тут ми бачимо перші несподівані (колись для мене: питання ) результати - TimeDelta
включається у вихід DataFrame
. Але як відповіли навпаки, це повинно бути так, але треба знати про це. Зверніть увагу , що bool
DTYPE пропускається, що може бути також небажаний для кого - то, але це з - за bool
і number
в різних « піддерев » з Numpy dtypes. У випадку з bool, ми можемо використовувати test.select_dtypes(['bool'])
тут.
Наступним обмеженням цього методу є те, що для поточної версії панд (0.24.2) цей код: test.select_dtypes('period')
підвищиться NotImplementedError
.
Інша справа, що він не може відрізняти рядки від інших об'єктів:
test.select_dtypes('object')
>>> str obj
>>> 0 s1 [1, 2, 3]
>>> 1 s2 [5435, 35, -52, 14]
Але це, по-перше, - вже згадується в документах. А друге - не проблема цього методу, скоріше те, як зберігаються рядки DataFrame
. Але в будь-якому випадку цей випадок повинен мати деяку поштову обробку.
5. df.api.types.is_XXX_dtype
підхід.
Цей приклад призначений для найбільш надійного та рідного способу досягнення розпізнавання типу (шлях модуля, де функції знаходяться, говорить сам по собі), як я припускаю. І це працює майже ідеально, але все-таки є хоча б один застереження і все-таки доведеться якось розрізняти рядкові стовпчики .
Крім того, це може бути суб'єктивним, але цей підхід також має більш number
групову обробку " типових для людини" груп обробки, порівняно з .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
Ні timedelta
і bool
включено. Ідеально.
Мій трубопровід в даний момент використовує саме цю функціональність, а також трохи опрацювання вручну.
Вихідні дані.
Сподіваюся, що я зміг аргументувати головне - що всі обговорювані підходи можуть використовуватися, але тільки pd.DataFrame.select_dtypes()
і pd.api.types.is_XXX_dtype
повинні бути дійсно розглянуті як застосовні.
string
не є типом