【问题标题】:How to use pandas to find consecutive same data in time series如何使用 pandas 在时间序列中查找连续的相同数据
【发布时间】:2015-01-10 18:34:08
【问题描述】:

这是一个像这样的时间序列数据,称之为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

【问题讨论】:

标签: python pandas apply


【解决方案1】:

应该这样做

df['value_grp'] = (df.Values.diff(1) != 0).astype('int').cumsum()

value_grp 将在 Value 更改时加一。下面,您可以提取分组结果

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)

【讨论】:

  • 您好 user1827356,感谢您的快速回答,但结果与我想要的不一样,您可以在答案下方看到我列出的结果。
  • @figo,我的错。 value_grp 计算中有错字。可以复查吗?您可以筛选 Consecutive > 1 以获得确切答案
  • 请注意,如果df.Values 不是数字,您仍然可以使用(df.Values != df.Values.shift()).cumsum()(不需要.astype(int)
  • 值得注意的是,您实际上并不需要“astype(int)”——pandas 恰好可以对布尔值求和。
【解决方案2】:

这是一个替代解决方案:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-03-12
    • 1970-01-01
    • 1970-01-01
    • 2019-05-16
    • 1970-01-01
    • 2018-05-29
    • 2021-10-25
    • 2015-12-14
    相关资源
    最近更新 更多