Tiêu đề câu hỏi được hỏi là chung chung, nhưng trường hợp sử dụng của tác giả nêu trong nội dung câu hỏi là cụ thể. Vì vậy, bất kỳ câu trả lời nào khác có thể được sử dụng.
Nhưng để trả lời đầy đủ câu hỏi tiêu đề , cần làm rõ rằng có vẻ như tất cả các cách tiếp cận có thể thất bại trong một số trường hợp và yêu cầu một số công việc lại. Tôi đã xem xét tất cả chúng (và một số bổ sung) theo thứ tự giảm dần độ tin cậy (theo ý kiến của tôi):
1. So sánh các loại trực tiếp qua ==
(câu trả lời được chấp nhận).
Mặc dù thực tế rằng đây là câu trả lời được chấp nhận và có hầu hết số phiếu ủng hộ, tôi nghĩ rằng phương pháp này hoàn toàn không nên được sử dụng. Vì trên thực tế cách làm này không được khuyến khích ở python như đã nói nhiều lần ở đây .
Nhưng nếu ta vẫn muốn sử dụng nó - nên lưu ý một số dtypes gấu trúc cụ thể như pd.CategoricalDType
, pd.PeriodDtype
hoặc pd.IntervalDtype
. Ở đây người ta phải sử dụng thêm type( )
để nhận ra dtype một cách chính xác:
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
Một lưu ý khác ở đây là loại đó nên được chỉ ra một cách chính xác:
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()
cách tiếp cận.
Phương pháp này vẫn chưa được đề cập trong các câu trả lời cho đến nay.
Vì vậy, nếu so sánh trực tiếp các kiểu không phải là một ý tưởng hay - hãy thử hàm python tích hợp sẵn cho mục đích này, cụ thể là - isinstance()
.
Nó không thành công ngay từ đầu, bởi vì giả định rằng chúng ta có một số đối tượng, nhưng pd.Series
hoặc pd.DataFrame
có thể được sử dụng chỉ như các vùng chứa rỗng với định sẵn dtype
nhưng không có đối tượng nào trong đó:
s = pd.Series([], dtype=bool)
s
>>> Series([], dtype: bool)
Nhưng nếu ai đó bằng cách nào đó khắc phục được vấn đề này và muốn truy cập vào từng đối tượng, chẳng hạn như ở hàng đầu tiên và kiểm tra loại dtype của nó như một cái gì đó tương tự:
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')
Nó sẽ gây hiểu nhầm trong trường hợp loại dữ liệu hỗn hợp trong một cột:
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')
Và cuối cùng nhưng không kém phần quan trọng - phương pháp này không thể trực tiếp nhận dạng Category
dtype. Như đã nêu trong tài liệu :
Việc trả lại một mục từ dữ liệu phân loại cũng sẽ trả về giá trị, không phải là một phân loại có độ dài “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')
Vì vậy phương pháp này cũng gần như không thể áp dụng được.
3. df.dtype.kind
cách tiếp cận.
Phương pháp này có thể hoạt động với trống pd.Series
hoặc pd.DataFrames
nhưng có vấn đề khác.
Đầu tiên - nó không thể khác biệt một số kiểu:
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
Thứ hai, điều gì thực sự vẫn chưa rõ ràng đối với tôi, nó thậm chí còn trả về trên một số loại Không có .
4. df.select_dtypes
cách tiếp cận.
Đây gần như là những gì chúng tôi muốn. Phương pháp này được thiết kế bên trong gấu trúc để nó xử lý hầu hết các trường hợp góc được đề cập trước đó - DataFrames trống, khác với các kiểu dtype đặc trưng cho gấu trúc hoặc không rõ ràng. Nó hoạt động tốt với loại đơn như .select_dtypes('bool')
. Nó có thể được sử dụng ngay cả để chọn nhóm cột dựa trên loại:
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')
Như vậy, như đã nêu trong tài liệu :
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 có thể nghĩ rằng ở đây chúng ta thấy kết quả bất ngờ đầu tiên (thường là đối với tôi: câu hỏi ) - TimeDelta
được đưa vào đầu ra DataFrame
. Nhưng như đã trả lời ngược lại, nó phải là như vậy, nhưng người ta phải nhận thức được nó. Lưu ý rằng bool
dtype bị bỏ qua, điều đó cũng có thể không mong muốn đối với một người nào đó, nhưng nó do bool
và number
nằm trong các " cây con " khác nhau của các loại numpy. Trong trường hợp với bool, chúng tôi có thể sử dụng test.select_dtypes(['bool'])
ở đây.
Hạn chế tiếp theo của phương pháp này là đối với phiên bản hiện tại của gấu trúc (0.24.2), mã này: test.select_dtypes('period')
sẽ tăng lên NotImplementedError
.
Và một điều nữa là nó không thể khác các chuỗi với các đối tượng khác:
test.select_dtypes('object')
>>> str obj
>>> 0 s1 [1, 2, 3]
>>> 1 s2 [5435, 35, -52, 14]
Nhưng điều này, trước tiên - đã được đề cập trong tài liệu. Và thứ hai - không phải là vấn đề của phương pháp này, mà là cách các chuỗi được lưu trữ trong đó DataFrame
. Nhưng dù sao trường hợp này cũng phải có một số bài xử lý.
5. df.api.types.is_XXX_dtype
cách tiếp cận.
Điều này được dự định là cách mạnh mẽ nhất và nguyên bản để đạt được nhận dạng dtype (đường dẫn của mô-đun nơi các hàm cư trú tự nó nói) như tôi cho là vậy. Và nó hoạt động gần như hoàn hảo, nhưng vẫn có ít nhất một cảnh báo và bằng cách nào đó vẫn phải phân biệt các cột chuỗi .
Bên cạnh đó, điều này có thể là chủ quan, nhưng cách tiếp cận này cũng có nhiều number
xử lý nhóm kiểu 'con người có thể hiểu được' hơn so với .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
Không timedelta
và bool
được bao gồm. Hoàn hảo.
Đường dẫn của tôi khai thác chính xác chức năng này tại thời điểm này, cộng với một chút xử lý bài đăng.
Đầu ra.
Hy vọng tôi có thể lập luận về điểm chính - rằng tất cả các phương pháp đã thảo luận có thể được sử dụng, nhưng chỉ pd.DataFrame.select_dtypes()
và pd.api.types.is_XXX_dtype
nên được thực sự coi là những phương pháp có thể áp dụng.
string
không phải là một dtype