ชื่อคำถามที่ถามเป็นเรื่องทั่วไป แต่ผู้เขียนใช้กรณีที่ระบุไว้ในเนื้อหาของคำถามนั้นเฉพาะเจาะจง ดังนั้นอาจใช้คำตอบอื่น ๆ
แต่เพื่อที่จะตอบคำถามชื่อเรื่องได้อย่างสมบูรณ์ควรชี้แจงว่าดูเหมือนว่าวิธีการทั้งหมดอาจล้มเหลวในบางกรณีและต้องมีการปรับปรุงใหม่ ฉันตรวจสอบทั้งหมด (และเพิ่มเติมบางส่วน) ในลำดับความน่าเชื่อถือที่ลดลง (ในความคิดของฉัน):
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()
แนวทาง
วิธีนี้ยังไม่ได้รับการกล่าวถึงในคำตอบ
ดังนั้นหากเปรียบเทียบโดยตรงของประเภทที่ไม่ได้เป็นความคิดที่ดี - ช่วยให้ลองฟังก์ชั่นหลามเพื่อวัตถุประสงค์นี้คือ 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
ประการที่สองสิ่งที่เป็นจริงยังไม่ชัดเจนสำหรับฉันมันแม้ผลตอบแทนจากการ dtypes บางไม่มี
4. df.select_dtypes
แนวทาง
นี่คือสิ่งที่เราต้องการเกือบทั้งหมด วิธีนี้ได้รับการออกแบบภายในแพนด้าเพื่อให้จัดการกับกรณีมุมส่วนใหญ่ที่กล่าวถึงก่อนหน้านี้ - DataFrames ว่างเปล่าแตกต่าง dtypes ที่เป็นตัวเลขหรือเฉพาะแพนด้าได้ดี มันทำงานได้ดีกับ dtype .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
อยู่ใน " subtrees " ของ numpy dtype ที่แตกต่างกัน ในกรณีที่มีบูลเราอาจใช้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
แนวทาง
วิธีนี้มีจุดมุ่งหมายเพื่อให้มีประสิทธิภาพมากที่สุดและเป็นวิธีดั้งเดิมในการรับรู้ประเภท dtype (เส้นทางของโมดูลที่ฟังก์ชันต่างๆอยู่กล่าวด้วยตัวเอง) ตามที่ฉันคิด และทำงานได้เกือบสมบูรณ์ แต่ยังมีข้อแม้อย่างน้อยหนึ่งข้อและยังต้องแยกแยะคอลัมน์สตริงด้วยด้วย
นอกจากนี้อาจเป็นเรื่องส่วนตัว แต่วิธีการนี้ยังมีnumber
การประมวลผลกลุ่ม dtypes ที่'มนุษย์เข้าใจได้' มากกว่าเมื่อเปรียบเทียบกับ.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
ไม่ใช่ dtype