【问题标题】:how to check the dtype of a column in python pandas如何检查python pandas中列的dtype
【发布时间】:2014-05-07 00:37:30
【问题描述】:

我需要使用不同的函数来处理数字列和字符串列。我现在做的真的很蠢:

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

【问题讨论】:

  • string 不是数据类型

标签: python pandas


【解决方案1】:

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

【讨论】:

  • 嗨大卫,你能评论一下你为什么包含 == np.float64 吗?我们不是在尝试转换为浮点数吗?谢谢。
  • @RyanChase 这个问题中的 OP 从未说过他正在转换为浮点数,他只需要知道是否使用(未指定)treat_numeric 函数。由于他将agg.dtypes==np.float64 作为一个选项,所以我也这样做了。
  • numpy中的数值类型比这两个还多,number下面的都在这里:docs.scipy.org/doc/numpy-1.13.0/reference/arrays.scalars.html一般的解决方案是is_numeric_dtype(agg[y])
【解决方案2】:

我知道这是一个旧线程,但使用 pandas 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

【讨论】:

  • 很好的答案,尽管我可能会为第一行做include[np.number](还包括整数和32位浮点数),为第二行做exclude[object]。就数据类型而言,字符串是对象。事实上,在对象中包含“字符串”会给我一个错误。
  • 似乎不再支持“string”,必须改用“object”。但绝对是正确的答案:)
  • 还应该注意'period' dtype 目前正在提高NotImplementedError (pandas 0.24.2)。所以可能需要一些手工后期处理。
【解决方案3】:

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

【讨论】:

  • 旧版 pandas 有什么替代方案吗?我收到错误:没有名为 api.types 的模块。
  • pandas.core.common.is_numeric_dtype 自 Pandas 0.13 以来就存在,它做同样的事情,但我认为在 0.19 中它已被弃用,取而代之的是 pandas.api.types.is_numeric_dtype
  • 这是最原生的答案。但是应该知道这里有一些caveats
  • df.apply(pd.api.types.is_numeric_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])

注意:

【讨论】:

  • ...dtype.kind 的问题在于它为句点和字符串/对象提供了'O'。最好使用pd.api.types.is_... 变体。
【解决方案5】:

问的问题标题很笼统,但问题正文中说明的作者用例是具体的。因此可以使用任何其他答案。

但为了完全回答 标题问题,应该澄清的是,在某些情况下,似乎所有方法都可能失败并且需要一些返工。我审查了所有这些(以及一些额外的)以降低可靠性顺序(在我看来):

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

尽管这是公认的答案并且有最多的赞成票,但我认为根本不应该使用这种方法。因为事实上这种方法在 python 中是不鼓励的,正如多次提到的here
但是,如果仍然想使用它 - 应该注意一些 pandas 特定的 dtype,例如 pd.CategoricalDTypepd.PeriodDtypepd.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() 接近。

到目前为止,答案中尚未提及此方法。

因此,如果直接比较类型不是一个好主意 - 让我们尝试为此目的内置 python 函数,即 - isinstance()
它刚开始就失败了,因为假设我们有一些对象,但 pd.Seriespd.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。如docs中所述:

从分类数据返回单个项目也将返回值,而不是长度为“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.Seriespd.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 None

4。 df.select_dtypes 接近。

这几乎就是我们想要的。这种方法在 pandas 内部设计,因此它可以处理前面提到的大多数极端情况 - 空 DataFrames,很好地区分 numpy 或 pandas 特定的 dtypes。它适用于像.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')

像这样,如docs中所述:

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

On 可能会认为我们在这里看到了第一个意想不到的(过去对我来说:question)结果 - TimeDelta 包含在输出 DataFrame 中。但正如answered 相反,它应该是这样,但必须意识到这一点。请注意,bool dtype 被跳过,这对于某些人来说可能也是不受欢迎的,但这是由于 boolnumber 位于不同的“subtrees”的 numpy dtypes 中。如果是 bool,我们可以在这里使用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]

但这是,首先 - 已经在文档中 mentioned。第二 - 不是这种方法的问题,而是字符串存储在DataFrame 中的方式。不过不管怎样,这个案子得有一些后期处理。

5。 df.api.types.is_XXX_dtype 接近。

我想这是实现 dtype 识别的最强大和最原生的方式(函数所在的模块的路径自己说)。它工作得几乎完美,但仍然有at least one caveat and still have to somehow distinguish string columns

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

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 应该真正被视为适用的。

【讨论】:

    【解决方案6】:

    漂亮地打印列数据类型

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

    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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-03-14
      • 2019-01-02
      • 1970-01-01
      • 1970-01-01
      • 2017-11-14
      • 2017-05-18
      相关资源
      最近更新 更多