问题:如何检查python pandas中列的dtype
我需要使用不同的函数来处理数字列和字符串列。我现在正在做的事情真是愚蠢:
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])
回答 0
您可以使用以下命令访问列的数据类型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
在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])
回答 2
我知道这有点旧,但是使用熊猫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
回答 3
问题标题是一般性的,但问题正文中所述的作者用例是特定的。因此,可以使用任何其他答案。
但是,为了完全回答标题问题,应澄清所有方法似乎在某些情况下可能会失败,并且需要进行一些重新设计。我以降低可靠性的顺序(我认为)对所有这些(以及其他一些)进行了审查:
1.通过==
(接受的答案)直接比较类型。
尽管这是公认的答案,并且投票最多,但我认为完全不应使用此方法。因为实际上,这种方法在python中不建议使用,如这里多次提到的。
但是,如果仍然想使用它-应该知道像一些熊猫专用dtypes的pd.CategoricalDType
,pd.PeriodDtype
或pd.IntervalDtype
。type( )
为了正确识别dtype,这里必须使用extra :
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)
但是,如果有人以某种方式克服了这个问题,并且想要访问每个对象,例如,在第一行中,并像这样检查其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')
最后但并非最不重要的一点-此方法无法直接识别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
还有其他问题。
首先-无法区分某些dtype:
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返回None。
4. df.select_dtypes
方法。
这几乎是我们想要的。此方法在pandas内部设计,因此可以处理前面提到的大多数极端情况-空的DataFrame,与numpy或特定于pandas的dtypes完全不同。与dtype这样的单个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
位于numpy dtype的不同“ 子树 ”中。如果是布尔型,我们可以test.select_dtypes(['bool'])
在这里使用。
此方法的下一个限制是,对于当前版本的Pandas(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
必须真正视为适用的。
回答 4
如果要将数据框列的类型标记为字符串,则可以执行以下操作:
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])
回答 5
漂亮地打印列数据类型
在例如从文件导入后检查数据类型
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