Pandas groupby datetime函数不保留dtype

时间:2017-04-17 04:25:30

标签: python pandas datetime

我在.minute聚合的上下文中无法提取Pandas datetime对象的groupby属性。

This post似乎涉及相同的根问题,但接受的答案只是解释了问题发生的原因(这是公平的,因为OP只是要求了解问题)。我现在正在发帖,因为我希望找到一个不依赖于明确更改数据类型的解决方案。

以下是一些示例代码:

import pandas as pd
ids = ['a','a','b','b']
dates = ['2017-01-01 01:01:00','2017-01-01 01:02:00',
         '2017-03-03 01:03:00','2017-03-03 01:04:00']
dates = pd.to_datetime(pd.Series(dates))
df = pd.DataFrame({'id':ids, 'datetime':dates})

  id             datetime     
0  a  2017-01-01 01:01:00
1  a  2017-01-01 01:02:00
2  b  2017-03-03 01:03:00
3  b  2017-03-03 01:04:00

我的目标是按id分组,然后提取每个datetime组中最早时间戳的分钟,作为整数值。

例如,要在所有 datetime值之间执行此操作,这样做有效:

df.datetime.min().minute  # returns 1

我想在groupby()设置中模仿相同的功能 但是,在UDF中组合min().minute时,分钟值将被添加到标记Unix纪元开始的日期时间的末尾:

def get_earliest_minute(tstamps):
    return tstamps.min().minute

df.groupby('id').agg({'datetime':get_earliest_minute})

                         datetime
id  
 a  1970-01-01 00:00:00.000000001
 b  1970-01-01 00:00:00.000000003

get_earliest_minute()返回的类型是一个整数:

def get_earliest_minute(tstamps):
    return type(tstamps.min().minute)

df.groupby('id').agg({'datetime':get_earliest_minute})

        datetime
id  
 a  <type 'int'>
 b  <type 'int'>

datetime后聚合的类型为<M8[ns]

df.groupby('id').agg({'datetime':get_earliest_minute}).datetime.dtype # dtype('<M8[ns]')

上面链接的帖子answer表明这是因为有目的的类型强制,它试图维护经历聚合的原始Series对象的类型。我已经环顾四周但是找不到任何解决方案,除了one comment之外建议在执行object之前将字段类型更改为groupby(),例如,

df.datetime = df.datetime.astype(object)
df.groupby('id').agg({'datetime':get_earliest_minute})

another comment建议在返回之前将函数的输出转换为float,例如,

def get_earliest_minute(tstamps):
    return float(tstamps.min().minute)

这些变通办法完成了这项工作(虽然由于某种原因声明int()不会像float()那样逃避类型强制,但是有没有办法对datetime对象进行这些groupby操作没有插入显式类型转换(即,推广<M8[ns] - &gt; object或转换int - &gt; float)?特别是,在多个agg()函数应用于datetime的情况下,某些函数依赖于日期时间属性而某些函数不依赖于日期时间属性,这将不会成功pre-groupby转换。

此外,float()类型转换是否会覆盖内置类型强制,但int()不会? 提前谢谢!

1 个答案:

答案 0 :(得分:1)

我会在这个问题上坚持使用@Jeff。 agg正在做我们想要的事情。它正在尝试保留dtype,因为它旨在聚合特定dtype的值。 当我汇总特定dtype的数据时,我期待同样的dtype ...

...也就是说,您可以使用apply

轻松解决此问题

您的问题

def get_earliest_minute(tstamps):
    return tstamps.min().minute

df.groupby('id').agg({'datetime':get_earliest_minute})

                        datetime
id                              
a  1970-01-01 00:00:00.000000001
b  1970-01-01 00:00:00.000000003

<强> 解决方法

def get_earliest_minute(tstamps):
    return tstamps.min().minute

df.groupby('id').datetime.apply(get_earliest_minute)

id
a    1
b    3
Name: datetime, dtype: int64