Python 通过多个索引分配groupby的结果,应用自定义函数,返回到父数据帧

Python 通过多个索引分配groupby的结果,应用自定义函数,返回到父数据帧,python,pandas,pandas-groupby,Python,Pandas,Pandas Groupby,我有一个数据帧,其中我希望按2列分组,从每组第3列的奇数行中减去偶数,并将结果分配给原始数据帧中的一列。不过,我从其他答案中尝试的东西似乎都不适合我 数据帧示例: ID Day OtherInfo log_timestamp A 17 foo t1 A 17 bar t2 A 18 footoo t3 A 18 bar_bar t4 其中log_timestamp是一个datetime对象 我想要

我有一个数据帧,其中我希望按2列分组,从每组第3列的奇数行中减去偶数,并将结果分配给原始数据帧中的一列。不过,我从其他答案中尝试的东西似乎都不适合我

数据帧示例:

    ID Day OtherInfo log_timestamp
    A  17   foo       t1
    A  17   bar       t2
    A  18   footoo    t3
    A  18   bar_bar   t4
其中log_timestamp是一个datetime对象

我想要的结果应该如下所示:

    ID Day OtherInfo log_timestamp duration
    A  17   foo       t1           (t2-t1)
    A  17   bar       t2 
    A  18   footoo    t3            (t4-t3)
    A  18   bar_bar   t4
我尝试过定义自己的函数、使用lambda函数和使用“apply”、“agg”、“map”和“transform”的组合,但还没有完全理解

>>my_df['duration']=my_df.groupby(['ID','day'])['log_timestamp'].agg({'duration':lambda series:(series-series.shift())[1::2]。重置_索引(drop=True)})
TypeError:插入列的索引与框架索引不兼容
>>>my_df['duration']=my_df['day'].map(my_df.groupby(['ID','day'])['log_timestamp'].apply({'duration':lambda series:(series-series.shift())[1::2]。重置_索引(drop=True)})
TypeError:无法损坏的类型:“dict”
>>>my_df['duration']=my_df.groupby(['ID','day'])['log\u timestamp'].transform(lambda series:(series-series.shift())[1::2]。重置_索引(drop=True))
ValueError:传递的值的长度为1,索引意味着2

我使用了以下测试数据帧(带有“true”时间戳):

从定义一个计算2个结果值的函数开始 来自2个源值(时间戳):

第一个返回值是差,第二个返回值是NaN

请按以下方式使用它:

df['duration'] = df.groupby(np.arange(len(df.index)) // 2)\
    .log_timestamp.transform(fn)
结果是:

  ID  Day OtherInfo       log_timestamp duration
0  A   17       foo 2019-09-01 10:20:00 01:10:00
1  A   17       bar 2019-09-01 11:30:00      NaT
2  A   18    footoo 2019-09-01 15:10:00 00:45:00
3  A   18   bar_bar 2019-09-01 15:55:00      NaT
groupby(np.arange(len(df.index))//2)是一个泛泛而谈的“习惯用法” 将数据帧(或系列)按2行(或元素)分组

然后transform(fn)生成一系列值,类似于 原始序列的“副本”(一对时间戳)

因此,第一个返回值——两个时间戳之间的差异——是 第一个元素的新值和第二个元素的NaN-值

因为目标列是时间戳类型,所以NaN是
转换为NaT。

这是一个出色的解决方案,但有一点需要澄清:我是否需要首先将numpy作为np导入?或者什么是np?是的,您应该将numpy作为np导入。Pandas是“在Numpy之上”构建的,因此它使用了一些在那里定义的常量。另一种选择是:代替np.nan,您可以只使用None。不需要导入Numpy,结果是一样的。
df['duration'] = df.groupby(np.arange(len(df.index)) // 2)\
    .log_timestamp.transform(fn)
  ID  Day OtherInfo       log_timestamp duration
0  A   17       foo 2019-09-01 10:20:00 01:10:00
1  A   17       bar 2019-09-01 11:30:00      NaT
2  A   18    footoo 2019-09-01 15:10:00 00:45:00
3  A   18   bar_bar 2019-09-01 15:55:00      NaT