我将以下数据转换为DataFrame,如下所示
data = [
{"start_ts": "2018-05-14 10:54:33", "end_ts": "2018-05-14 11:54:33", "product": "a", "value": 1},
{"start_ts": "2018-05-14 11:54:33", "end_ts": "2018-05-14 12:54:33", "product": "a", "value": 1},
{"start_ts": "2018-05-14 13:54:33", "end_ts": "2018-05-14 14:54:33", "product": "a", "value": 1},
{"start_ts": "2018-05-14 10:54:33", "end_ts": "2018-05-14 11:54:33", "product": "b", "value": 1}
]
product start_ts end_ts value
0 a 2018-05-14 10:54:33 2018-05-14 11:54:33 1
1 a 2018-05-14 11:54:33 2018-05-14 12:54:33 1
2 a 2018-05-14 13:54:33 2018-05-14 14:54:33 1
3 b 2018-05-14 10:54:33 2018-05-14 11:54:33 1
我试图通过查找产品的连续时间戳字段(其中start_ts等于产品的前一行的end_ts)并将值列总和如下所示,将DF行上面的行划分为一行。
预期:
product start_ts end_ts value
0 a 2018-05-14 10:54:33 2018-05-14 12:54:33 2
1 a 2018-05-14 13:54:33 2018-05-14 14:54:33 1
2 b 2018-05-14 10:54:33 2018-05-14 11:54:33 1
我无法使用下面的代码获得预期的上述值
def merge_dates(grp):
date_groups = (grp['start_ts'] != grp['end_ts'].shift())
return grp.groupby(date_groups).agg({'start_ts': 'first', 'end_ts': 'last'})
df.groupby(["product"]).apply(merge_dates)
需要一些建议。任何帮助将不胜感激!
由于
答案 0 :(得分:3)
我相信这会奏效:
df.groupby(['product', (df.start_ts != df.end_ts.shift()).cumsum()], \
as_index=False).agg({'start_ts':min, 'end_ts':max, 'value':sum})
# product end_ts start_ts value
# 0 a 2018-05-14 12:54:33 2018-05-14 10:54:33 2
# 1 a 2018-05-14 14:54:33 2018-05-14 13:54:33 1
# 2 b 2018-05-14 11:54:33 2018-05-14 10:54:33 1
此方法按产品和cumsum
创建的布尔系列的df.start_ts != df.end_ts.shift()
分组;布尔系列用作计数器,每次df.start_ts
不等于前一行的end_ts
(即df.end_ts.shift()
)时增加1,从而指示新组何时应该开始。