Pandas通过datetime和id来创建rame,但具有随机大小的组

ncgqoxb0  于 2023-10-14  发布在  其他
关注(0)|答案(1)|浏览(107)

我有这样的问题,我有列:ID、日期和值。我需要按id和日期分组,以便在一个组中,日期值彼此之间的距离不应超过7天。
数据如下所示:

df = pd.DataFrame({'id' : [1, 2, 2, 3, 3, 3, 4], 'date' : ['2019-02-28', '2019-02-27', '2019-02-28', '2019-02-1', '2019-02-2', '2019-03-20', '2019-02-28'], 'value' : ['a', 'b', 'c', 'c', 'a', 'b', 'c']})

我想把日期组的最早日期,列一个值的列表。
我希望有这样的东西:

| id       | date       | value      |
| -------- | ---------- | ---------- |
| 1        | 2019-02-28 | ['a']      |
| 2        | 2019-02-27 | ['b', 'c'] |
| 3        | 2019-02-1  | ['c', 'a'] |
| 3        | 2019-03-20 | ['b']      |
| 4        | 2019-02-28 | ['c']      |

注意id组可以有多个不同的datetime组。
我发现很难对datetime值进行排序,并同时进行此groupby,同时检查与旁边行的日期差是否低于7天。

5f0d552i

5f0d552i1#

您可以首先使用自定义groupby.transform来识别超过7天的间隙,然后使用groupby.agg

df['date'] = pd.to_datetime(df['date'], dayfirst=False)

group = (df.groupby('id')['date']
         .transform(lambda s: s.diff().gt('7D').cumsum())
        )

out = (df.groupby(['id', group], as_index=False)
         .agg({'date': 'min', 'value': list})
      )

输出量:

id       date   value
0   1 2019-02-28     [a]
1   2 2019-02-27  [b, c]
2   3 2019-02-01  [c, a]
3   3 2019-03-20     [b]
4   4 2019-02-28     [c]

如果您想确保组内的所有日期都在7天内(例如,连续的天数应该在7行后拆分),那么你需要一个自定义函数:

def grouper(s, thresh='7D'):
    groups = []
    group = 0
    ref = s.iloc[0]
    for date in s:
        if (date-ref) >= pd.Timedelta(thresh):
            group += 1
            ref = date
        groups.append(group)
    return pd.Series(groups, index=s.index)

out = (df.groupby(['id', df.groupby('id')['date'].transform(grouper)],
                  as_index=False)
         .agg({'date': 'min', 'value': list})
      )

相关问题