这里有一个这样的时间序列数据,称之为 df:
'No' 'Date' 'Value'
0 600000 1999-11-10 1
1 600000 1999-11-11 1
2 600000 1999-11-12 1
3 600000 1999-11-15 1
4 600000 1999-11-16 1
5 600000 1999-11-17 1
6 600000 1999-11-18 0
7 600000 1999-11-19 1
8 600000 1999-11-22 1
9 600000 1999-11-23 1
10 600000 1999-11-24 1
11 600000 1999-11-25 0
12 600001 1999-11-26 1
13 600001 1999-11-29 1
14 600001 1999-11-30 0
我想获取连续'Value'为1的日期范围,那么如何得到最终结果如下:
'No' 'BeginDate' 'EndDate' 'Consecutive'
0 600000 1999-11-10 1999-11-17 6
1 600000 1999-11-19 1999-11-24 4
2 600001 1999-11-26 1999-11-29 2
这样应该可以了
df['value_grp'] = (df.Values.diff(1) != 0).astype('int').cumsum()
每当 Value 改变时,value_grp 就会加一。下面,您可以提取分组结果
pd.DataFrame({'BeginDate' : df.groupby('value_grp').Date.first(),
'EndDate' : df.groupby('value_grp').Date.last(),
'Consecutive' : df.groupby('value_grp').size(),
'No' : df.groupby('value_grp').No.first()}).reset_index(drop=True)
这里有一个替代解决方案:
rslt = (df.assign(Consecutive=df.Value
.groupby((df.Value != df.Value.shift())
.cumsum())
.transform('size'))
.query('Consecutive > 1')
.groupby('Consecutive')
.agg({'No':{'No':'first'}, 'Date': {'BeginDate':'first', 'EndDate':'last'}})
.reset_index()
)
rslt.columns = [t[1] if t[1] else t[0] for t in rslt.columns]
演示:
In [225]: %paste
rslt = (df.assign(Consecutive=df.Value
.groupby((df.Value != df.Value.shift())
.cumsum())
.transform('size'))
.query('Consecutive > 1')
.groupby('Consecutive')
.agg({'No':{'No':'first'}, 'Date': {'BeginDate':'first', 'EndDate':'last'}})
.reset_index()
)
rslt.columns = [t[1] if t[1] else t[0] for t in rslt.columns]
## -- End pasted text --
In [226]: rslt
Out[226]:
Consecutive BeginDate EndDate No
0 2 1999-11-26 1999-11-29 600001
1 4 1999-11-19 1999-11-24 600000
2 6 1999-11-10 1999-11-17 600000
def function1(dd1:pd.DataFrame):
col1=dd1.Value
col2=(~(col1.eq(1)&col1.diff().eq(0))).cumsum()
dd2=dd1.assign(col2=col2).sql().aggregate(aggr_expr="no,min(date) BeginDate,max(date) EndDate,count(1) Consecutive",group_expr="no,col2").filter("Consecutive>1")
return dd2.to_df()
df1.groupby(['No'],as_index=False).apply(function1).reset_index(drop=1)
:
┌───────┬────────┬────────────┬────────────┬─────────────┐
│ index │ No │ BeginDate │ EndDate │ Consecutive │
│ int64 │ int64 │ varchar │ varchar │ int64 │
├───────┼────────┼────────────┼────────────┼─────────────┤
│ 0 │ 600000 │ 1999-11-19 │ 1999-11-24 │ 4 │
│ 1 │ 600000 │ 1999-11-10 │ 1999-11-17 │ 6 │
│ 2 │ 600001 │ 1999-11-26 │ 1999-11-29 │ 2 │
└───────┴────────┴────────────┴────────────┴─────────────┘