我有一个系列,它的状态可以是真或假。它有一个 MultiIndex,第一级用于 ID,第二级用于每个 ID 中的一集,第三级用于记录状态的日期。
ID Episode Date Status
foo 1 2019-02-01 False
2019-02-02 True
2019-02-03 True
2019-02-04 False
2 2019-02-05 True
2019-02-06 True
2019-02-07 False
3 2019-02-08 False
2019-02-09 True
2019-02-10 True
bar 1 2019-03-03 False
2019-03-04 True
2 2019-03-05 True
2019-03-06 True
2019-03-07 False
2019-03-08 True
2019-03-09 False
我想将剧集中的状态开始为真以及何时停止为真提取到数据帧。对于此示例,结果应如下所示:
ID Episode Start Dates End Dates
foo 1 2019-02-02 2019-03-03
2 2019-02-05 2019-02-06
3 2019-02-09 2019-02-10
bar 1 2019-03-04 2019-03-04
2 2019-03-05, 2019-03-08 2019-03-06, 2019-03-08
检查使用 groupby
与cumsum
组创建内部键,下一步我们根据 df 中的所有True
值进行过滤,然后我们使用新键和first
last
进行另一轮groupby
,join
结果
s=(~df.Status).groupby(level=['ID','Episode']).cumsum().reset_index()
s[df.Status.values].groupby(['ID','Episode','Status'])['Date'].agg(['first','last']).groupby(level=[0,1]).agg(','.join)
Out[104]:
first last
ID Episode
bar 1 2019-03-04 2019-03-04
2 2019-03-05,2019-03-08 2019-03-06,2019-03-08
foo 1 2019-02-02 2019-02-03
2 2019-02-05 2019-02-06
3 2019-02-09 2019-02-10
您还可以
使用将Status
列移动一pandas.Series.shift
。
df['prev_Status'] = df['Status'].shift(1)
df['next_Status'] = df['Status'].shift(-1)
Status prev_Status next_Status
Date
foo 1 2019-02-01 False NaN True
2019-02-02 True False True
2019-02-03 True True False
2019-02-04 False True True
2 2019-02-05 True False True
2019-02-06 True True False
一旦移位,您可以在打开True
时按预期进行查询
df.query('prev_Status=="False"').query('Status=="True"').groupby(level=[0,1]).Date.agg(','.join)
bar 1 2019-03-04
2 2019-03-08
foo 1 2019-02-02
2 2019-02-05
3 2019-02-09
Name: Date, dtype: object
或者何时关闭
df.query('Status=="True"').query('next_Status=="False"').groupby(level=[0,1]).Date.agg(','.join)
bar 2 2019-03-06,2019-03-08
foo 1 2019-02-03
2 2019-02-06
3 2019-02-10
Name: Date, dtype: object
有人可能会争辩说,这比另一个(非常好(答案效率低,但更容易理解。