Judul pertanyaan yang ditanyakan bersifat umum, tetapi kasus penggunaan penulis yang tertera di badan pertanyaan bersifat spesifik. Jadi jawaban lain dapat digunakan.
Tetapi untuk sepenuhnya menjawab pertanyaan judul , harus diklarifikasi bahwa tampaknya semua pendekatan mungkin gagal dalam beberapa kasus dan memerlukan beberapa pengerjaan ulang. Saya meninjau semuanya (dan beberapa tambahan) dalam penurunan urutan keandalan (menurut saya):
1. Membandingkan tipe secara langsung melalui ==(jawaban yang diterima).
Terlepas dari kenyataan bahwa ini adalah jawaban yang diterima dan memiliki jumlah suara positif terbanyak, saya pikir metode ini tidak boleh digunakan sama sekali. Karena sebenarnya pendekatan ini tidak dianjurkan pada python seperti yang disebutkan beberapa kali di sini .
Tetapi jika salah satu masih ingin menggunakannya - harus menyadari beberapa dtypes panda-spesifik seperti pd.CategoricalDType, pd.PeriodDtype, atau pd.IntervalDtype. Di sini seseorang harus menggunakan ekstra type( )untuk mengenali dtype dengan benar:
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
Peringatan lain di sini adalah jenis itu harus ditunjukkan dengan tepat:
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()pendekatan.
Metode ini belum disebutkan dalam jawaban sejauh ini.
Jadi jika membandingkan tipe secara langsung bukanlah ide yang baik - mari coba fungsi python built-in untuk tujuan ini, yaitu - isinstance().
Ini gagal hanya pada awalnya, karena mengasumsikan bahwa kita memiliki beberapa objek, tetapi pd.Seriesatau pd.DataFramedapat digunakan hanya sebagai wadah kosong dengan yang telah ditentukan dtypetetapi tidak ada objek di dalamnya:
s = pd.Series([], dtype=bool)
s
>>> Series([], dtype: bool)
Tetapi jika seseorang mengatasi masalah ini, dan ingin mengakses setiap objek, misalnya, di baris pertama dan memeriksa dtype-nya seperti itu:
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')
Ini akan menyesatkan dalam kasus jenis data campuran dalam satu kolom:
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')
Dan yang tak kalah pentingnya - metode ini tidak dapat langsung mengenali Categorydtype. Seperti yang dinyatakan dalam dokumen :
Mengembalikan satu item dari data kategori juga akan mengembalikan nilai, bukan kategori dengan panjang "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')
Jadi metode ini juga hampir tidak bisa diterapkan.
3. df.dtype.kindpendekatan.
Metode ini mungkin berfungsi dengan kosong pd.Seriesatau pd.DataFramestetapi memiliki masalah lain.
Pertama - tidak dapat membedakan beberapa tipe dt:
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
Kedua, apa yang sebenarnya masih belum jelas bagi saya, bahkan mengembalikan beberapa dtypes None .
4. df.select_dtypespendekatan.
Ini hampir seperti yang kita inginkan. Metode ini dirancang di dalam pandas sehingga menangani sebagian besar kasus sudut yang disebutkan sebelumnya - DataFrames kosong, berbeda dengan baik jenis dtype numpy atau pandas tertentu. Ia bekerja dengan baik dengan tipe dtype tunggal seperti .select_dtypes('bool'). Ini dapat digunakan bahkan untuk memilih kelompok kolom berdasarkan 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')
Seperti itu, seperti yang dinyatakan dalam dokumen :
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
Pada mungkin berpikir bahwa di sini kita melihat hasil tak terduga pertama (dulu bagi saya: pertanyaan ) - TimeDeltadimasukkan ke dalam output DataFrame. Tetapi seperti yang dijawab sebaliknya, seharusnya demikian, tetapi orang harus menyadarinya. Perhatikan bahwa booldtype dilewati, yang mungkin juga tidak diinginkan oleh seseorang, tetapi hal itu disebabkan booldan numberberada dalam " subpohon " yang berbeda dari dtypes numpy. Dalam kasus dengan bool, kami dapat menggunakan di test.select_dtypes(['bool'])sini.
Batasan selanjutnya dari metode ini adalah untuk versi panda saat ini (0.24.2), kode ini: test.select_dtypes('period')akan muncul NotImplementedError.
Dan hal lainnya adalah ia tidak dapat membedakan string dari objek lain:
test.select_dtypes('object')
>>> str obj
>>> 0 s1 [1, 2, 3]
>>> 1 s2 [5435, 35, -52, 14]
Tapi ini, pertama - sudah disebutkan di dokumen. Dan kedua - bukan masalah metode ini, melainkan cara string disimpan DataFrame. Tapi bagaimanapun kasus ini harus memiliki beberapa proses pasca.
5. df.api.types.is_XXX_dtypependekatan.
Yang ini dimaksudkan untuk menjadi cara yang paling kuat dan asli untuk mencapai pengenalan dtype (jalur modul tempat fungsi berada mengatakan dengan sendirinya) seperti yang saya kira. Dan itu bekerja hampir sempurna, tetapi masih memiliki setidaknya satu peringatan dan masih harus membedakan kolom string .
Selain itu, ini mungkin subjektif, tetapi pendekatan ini juga memiliki numberpemrosesan kelompok tipe yang lebih 'dapat dimengerti manusia' dibandingkan dengan .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
Tidak timedeltadan booldisertakan. Sempurna.
Pipeline saya mengeksploitasi fungsi ini dengan tepat pada saat ini, ditambah sedikit pemrosesan pasca tangan.
Keluaran.
Harapan saya dapat menjelaskan poin utama - bahwa semua pendekatan yang dibahas dapat digunakan, tetapi hanya pd.DataFrame.select_dtypes()dan pd.api.types.is_XXX_dtypeharus benar-benar dianggap sebagai pendekatan yang dapat diterapkan.
stringbukan dtype