如何检查一个列的 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])
368369 次浏览

您可以使用 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])

我知道这有点老套,但对于熊猫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

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

如果要将数据框列的类型标记为字符串,可以这样做:

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

注:

提出的问题题名是一般性的,但作者用例说明的问题正文是具体的。所以任何其他的答案都可以使用。

但是为了完全回答 < em > 题目问题 ,似乎所有的方法都可能在某些情况下 失败,需要一些返工。我回顾了所有这些(以及一些额外的)在减少可靠性顺序方面(在我看来) :

1. 通过 ==直接比较类型(可接受的答案)。

尽管事实上,这是接受的答案,并有大多数赞成票计数,我认为这种方法不应该使用的。因为实际上这种方法在 python 中是 气馁,如前面多次提到的 给你
但是,如果你仍然想使用它-应该知道一些熊猫特有的 dtype,如 pd.CategoricalDTypepd.PeriodDtype,或 pd.IntervalDtype。在这里,为了正确识别 dtype,必须使用额外的 type( ):

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

其次,对我来说还不清楚的是,它甚至在一些 dtype 没有上返回。

4. df.select_dtypes进场。

这几乎就是我们想要的。这个方法设计在熊猫内部,因此它可以处理前面提到的大多数角落情况——空 DataFrames,与 numpy 或熊猫特有的 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,这可能对某些人来说也是不希望的,但这是由于 boolnumber处于不同的“ 子树”数字 dtype。为了防止 bool,我们可以在这里使用 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 识别(函数驻留的模块的路径自己说明)的最健壮和本机的方法。它的工作几乎完美,但仍然有 至少有一点需要注意,仍然必须以某种方式区分字符串列

此外,这可能是主观的,但与 .select_dtypes('number')相比,这种方法也具有更多的“人类可理解的”number dtype 组处理:

for col in test.columns:
if pd.api.types.is_numeric_dtype(test[col]):
print (test[col].dtype)


>>> bool
>>> int64
>>> int32
>>> float64
>>> complex128

没有 timedeltabool包括。完美。

此时此刻,我的管道正好利用了这个功能,加上一点事后处理。

输出。

希望我能够论证主要观点——所有讨论过的方法都可以使用,但是只有 pd.DataFrame.select_dtypes()pd.api.types.is_XXX_dtype应该被认为是真正适用的方法。

打印列数据类型

检查数据类型,例如在从文件导入之后

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