अजगर पंडों में एक कॉलम के dtype की जांच कैसे करें


133

मुझे संख्यात्मक कॉलम और स्ट्रिंग कॉलम के इलाज के लिए विभिन्न कार्यों का उपयोग करने की आवश्यकता है। अब मैं जो कर रहा हूं वह वास्तव में गूंगा है:

allc = list((agg.loc[:, (agg.dtypes==np.float64)|(agg.dtypes==np.int)]).columns)
for y in allc:
    treat_numeric(agg[y])    

allc = list((agg.loc[:, (agg.dtypes!=np.float64)&(agg.dtypes!=np.int)]).columns)
for y in allc:
    treat_str(agg[y])    

क्या ऐसा करने का अधिक सुरुचिपूर्ण तरीका है? उदाहरण के लिए

for y in agg.columns:
    if(dtype(agg[y]) == 'string'):
          treat_str(agg[y])
    elif(dtype(agg[y]) != 'string'):
          treat_numeric(agg[y])

2
stringDtype नहीं है
डेविड रॉबिन्सन

जवाबों:


124

आप किसी कॉलम के डेटा-प्रकार तक पहुँच सकते हैं dtype:

for y in agg.columns:
    if(agg[y].dtype == np.float64 or agg[y].dtype == np.int64):
          treat_numeric(agg[y])
    else:
          treat_str(agg[y])

1
हाय डेविड, क्या आप टिप्पणी कर सकते हैं कि आपने == np.float64 को क्यों शामिल किया? क्या हम झांकियों में बदलने की कोशिश नहीं कर रहे हैं? धन्यवाद।
रयान चेस

@RyanChase इस प्रश्न में ओपी ने कभी नहीं कहा कि वह फ्लोट में परिवर्तित हो रहा है, उसे सिर्फ यह जानना आवश्यक है कि क्या एक (अनिर्दिष्ट) treat_numericफ़ंक्शन का उपयोग करना है। चूंकि उन्होंने agg.dtypes==np.float64एक विकल्प के रूप में शामिल किया, मैंने भी किया।
डेविड रॉबिन्सन

3
इन दोनों की तुलना में संख्यात्मक रूप से अधिक संख्यात्मक प्रकार हैं, numberयहां सब कुछ नीचे दिया गया है: docs.scipy.org/doc/numpy-1.13.0/reference/arrays.scalars.html सामान्य समाधान हैis_numeric_dtype(agg[y])
एटिला

96

में pandas 0.20.2आप कर सकते हैं:

from pandas.api.types import is_string_dtype
from pandas.api.types import is_numeric_dtype

is_string_dtype(df['A'])
>>>> True

is_numeric_dtype(df['B'])
>>>> True

तो आपका कोड बन जाता है:

for y in agg.columns:
    if (is_string_dtype(agg[y])):
        treat_str(agg[y])
    elif (is_numeric_dtype(agg[y])):
        treat_numeric(agg[y])

1
क्या पुराने पांडा संस्करणों के लिए कोई विकल्प है? मुझे त्रुटि मिलती है: कोई मॉड्यूल जिसका नाम api.types नहीं है।
एनएफ

2
pandas.core.common.is_numeric_dtypeपंडों ०.१३ के बाद से अस्तित्व में है, और यह वही काम करता है, लेकिन यह pandas.api.types.is_numeric_dtype०.१ ९ के पक्ष में पदावनत हो गया , मुझे लगता है
मिगवेल

यह सबसे मूल जवाब है। लेकिन यहां कुछ कैविएट के बारे में पता होना चाहिए ।
इससे पहले

46

मुझे पता है कि यह एक पुराना धागा है लेकिन पंडों के साथ 19.02, आप कर सकते हैं:

df.select_dtypes(include=['float64']).apply(your_function)
df.select_dtypes(exclude=['string','object']).apply(your_other_function)

http://pandas.pydata.org/pandas-docs/version/0.19.2/generated/pandas.DataFrame.select_dtypes.html


1
अच्छा जवाब अल्थो मैं शायद include[np.number](पहली पंक्ति के exclude[object]लिए और दूसरी पंक्ति के लिए इन्टस और 32 बिट फ़्लोट्स को भी शामिल करूँगा ) । स्ट्रिंग्स ऑब्जेक्ट हैं जहां तक ​​dtypes का संबंध है। वास्तव में, ऑब्जेक्ट के साथ 'स्ट्रिंग' सहित मुझे एक त्रुटि मिलती है।
जॉन सेप

1
ऐसा लगता है कि "स्ट्रिंग" अब समर्थित नहीं है, इसके बजाय "ऑब्जेक्ट" का उपयोग किया जाना चाहिए। लेकिन निश्चित रूप से सही उत्तर :)
बर्ट्रेंड

यह भी ध्यान दिया जाना चाहिए कि 'period'dtype NotImplementedErrorअभी के लिए बढ़ रहा है (पांडा 0.24.2)। तो किसी को कुछ हस्तनिर्मित पोस्ट प्रोसेसिंग की आवश्यकता हो सकती है।
BeforeFlight

21

पूछे जाने वाले प्रश्न का शीर्षक सामान्य है, लेकिन लेखक प्रश्न के शरीर में वर्णित मामले का उपयोग करते हैं, विशिष्ट है। तो किसी अन्य उत्तर का उपयोग किया जा सकता है।

लेकिन शीर्षक प्रश्न का पूरी तरह से उत्तर देने के लिए यह स्पष्ट किया जाना चाहिए कि ऐसा लगता है कि सभी दृष्टिकोण कुछ मामलों में विफल हो सकते हैं और कुछ पुन: कार्य की आवश्यकता होती है। मैंने विश्वसनीयता क्रम घटने में उन सभी (और कुछ अतिरिक्त) की समीक्षा की (मेरी राय में):

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)

लेकिन अगर कोई किसी तरह इस मुद्दे को दूर करता है, और प्रत्येक वस्तु तक पहुंचना चाहता है, उदाहरण के लिए, पहली पंक्ति में और इसके dtype की जाँच करता है जैसे:

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')

और अंतिम लेकिन कम से कम नहीं - यह विधि सीधे Categorydtype को नहीं पहचान सकती है। डॉक्स में कहा गया है :

श्रेणीबद्ध डेटा से किसी एक आइटम को वापस करना भी मान लौटाएगा, लंबाई "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एक और समस्या है।

पहला - यह कुछ 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

दूसरा, क्या मेरे लिए वास्तव में अभी भी स्पष्ट नहीं है, तो यह और भी कुछ dtypes पर रिटर्न नहीं

4. df.select_dtypesदृष्टिकोण।

यह लगभग वही है जो हम चाहते हैं। यह विधि पांडा के अंदर डिज़ाइन की गई है इसलिए यह पहले बताए गए अधिकांश कोने के मामलों को संभालती है - खाली डेटाफ्रैम, सुन्न या पांडा-विशिष्ट 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 dtypes की"। बूल के मामले में, हम 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 मान्यता प्राप्त करने के लिए सबसे मजबूत और देशी तरीका है (मॉड्यूल का कार्य जहां फ़ंक्शन रहता है अपने आप से कहता है) जैसे कि मुझे लगता है। और यह लगभग पूरी तरह से काम करता है, लेकिन अभी भी कम से कम एक चेतावनी है और अभी भी किसी न किसी तरह से स्ट्रिंग कॉलम को भेद करना है

इसके अलावा, यह व्यक्तिपरक हो सकता है, लेकिन इस दृष्टिकोण में 'मानव-समझने योग्य' numberdtypes समूह प्रसंस्करण की तुलना भी अधिक है .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वास्तव में लागू लोगों के रूप में माना जाना चाहिए।


1
महान और अच्छी तरह से तैयार जवाब। :-)
ओलिवर

8

यदि आप एक स्ट्रिंग के रूप में डेटाफ्रेम कॉलम के प्रकार को चिह्नित करना चाहते हैं, तो आप कर सकते हैं:

df['A'].dtype.kind

एक उदाहरण:

In [8]: df = pd.DataFrame([[1,'a',1.2],[2,'b',2.3]])
In [9]: df[0].dtype.kind, df[1].dtype.kind, df[2].dtype.kind
Out[9]: ('i', 'O', 'f')

आपके कोड का उत्तर:

for y in agg.columns:
    if(agg[y].dtype.kind == 'f' or agg[y].dtype.kind == 'i'):
          treat_numeric(agg[y])
    else:
          treat_str(agg[y])

4

स्तंभ डेटा प्रकारों को सुंदर रूप से प्रिंट करने के लिए

उदाहरण के लिए, बाद में डेटा प्रकार की जांच करने के लिए, एक फ़ाइल से एक आयात

def printColumnInfo(df):
    template="%-8s %-30s %s"
    print(template % ("Type", "Column Name", "Example Value"))
    print("-"*53)
    for c in df.columns:
        print(template % (df[c].dtype, c, df[c].iloc[1]) )

इलस्ट्रेटिव आउटपुट:

Type     Column Name                    Example Value
-----------------------------------------------------
int64    Age                            49
object   Attrition                      No
object   BusinessTravel                 Travel_Frequently
float64  DailyRate                      279.0
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.