【问题标题】:Assigning results of groupby multiple indices, apply custom function, back to parent dataframe分配 groupby 多个索引的结果,应用自定义函数,返回父数据框
【发布时间】:2019-10-26 02:32:58
【问题描述】:

我有一个数据框,我想在其中对 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 是一个日期时间对象。

我想要的结果应该是这样的:

    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].reset_index(drop=True)})
TypeError: incompatible index of inserted column with frame index

>>>my_df['duration'] = my_df['day'].map(my_df.groupby(['ID', 'day'])['log_timestamp'].apply({'duration': lambda series: (series - series.shift())[1::2].reset_index(drop=True)}))
TypeError: unhashable type: 'dict'

>>>my_df['duration'] = my_df.groupby(['ID', 'day'])['log_timestamp'].transform(lambda series: (series - series.shift())[1::2].reset_index(drop=True))
ValueError: Length of passed values is 1, index implies 2

【问题讨论】:

    标签: python pandas pandas-groupby


    【解决方案1】:

    我使用了 followitg 测试 DataFrame(带有“真实”时间戳):

      ID  Day OtherInfo       log_timestamp
    0  A   17       foo 2019-09-01 10:20:00
    1  A   17       bar 2019-09-01 11:30:00
    2  A   18    footoo 2019-09-01 15:10:00
    3  A   18   bar_bar 2019-09-01 15:55:00
    

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

    def fn(grp):
        return [grp.iloc[1] - grp.iloc[0], np.nan]
    

    第一个返回值是差值,第二个 - 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) 是 pandasonic “成语” 将 DataFrame(或 Series)按 2 行(或元素)分组。

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

    所以第一个返回值 - 两个时间戳之间的差异 - 是 第一个元素的新值和 NaN - 第二个元素。

    因为目标列是 Timestamp 类型,所以 NaN 是 转换为 NaT

    【讨论】:

    • 这是一个绝妙的解决方案,但需要澄清一点:我需要先将 numpy 导入为 np 吗?或者什么是 np?
    • 是的,你应该import numpy as npPandas 构建在“Numpy 之上”,因此它使用了一些在那里定义的常量。
    • 另一种选择:您可以只使用 None 来代替 np.nan。无需导入Numpy,结果是一样的。
    猜你喜欢
    • 2021-10-02
    • 2021-01-12
    • 1970-01-01
    • 2013-07-07
    • 2012-08-25
    • 1970-01-01
    • 2011-06-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多