Pandas - groupby连续日期时间段

时间:2017-11-25 11:07:21

标签: python pandas pandas-groupby

我有一个像这样的pandas数据框:

    KEY   START       END         VALUE
0   A     2017-01-01  2017-01-16  2.1
1   B     2017-01-01  2017-01-23  4.3
2   B     2017-01-23  2017-02-10  1.7
3   A     2017-01-28  2017-02-02  4.2
4   A     2017-02-02  2017-03-01  0.8  

我希望groupby上的KEYsum上的VALUE,但仅限于连续的时间段。例如,在上面的例子中我想得到:

   KEY  START       END         VALUE 
0  A    2017-01-01  2017-01-16  2.1
1  A    2017-01-28  2017-03-01  5.0
2  B    2017-01-01  2017-02-10  6.0

A有两组,因为时间段有差距。 我想避免for循环,因为数据帧有数千万行。

2 个答案:

答案 0 :(得分:1)

通过每组比较shift ed Series列创建帮助START,并将其用于groupby

s = df.loc[df.groupby('KEY')['START'].shift(-1) == df['END'], 'END']
s = s.combine_first(df['START'])
print (s)
0   2017-01-01
1   2017-01-23
2   2017-01-23
3   2017-02-02
4   2017-02-02
Name: END, dtype: datetime64[ns]

df = df.groupby(['KEY', s], as_index=False).agg({'START':'first','END':'last','VALUE':'sum'})
print (df)
  KEY  VALUE      START        END
0   A    2.1 2017-01-01 2017-01-16
1   A    5.0 2017-01-28 2017-03-01
2   B    6.0 2017-01-01 2017-02-10

答案 1 :(得分:0)

如果只有两个连续的行聚合,那么jezrael的答案就像一个魅力。在新示例中,它不会聚合KEY = A的最后三行。

     KEY   START       END         VALUE
 0   A     2017-01-01  2017-01-16  2.1
 1   B     2017-01-01  2017-01-23  4.3
 2   B     2017-01-23  2017-02-10  1.7
 3   A     2017-01-28  2017-02-02  4.2
 4   A     2017-02-02  2017-03-01  0.8 
 5   A     2017-03-01  2017-03-23  1.0

以下解决方案(对jezrael解决方案稍作修改)可以聚合应聚合的所有行:

df = df.sort_values(by='START')
idx = df.groupby('KEY')['START'].shift(-1) != df['END']
df['DATE'] = df.loc[idx, 'START']
df['DATE'] = df.groupby('KEY').DATE.fillna(method='backfill')
df = (df.groupby(['KEY', 'DATE'], as_index=False)
        .agg({'START': 'first', 'END': 'last', 'VALUE': 'sum'})
        .drop(['DATE'], axis=1))

给出了:

   KEY   START         END      VALUE
0   A  2017-01-01  2017-01-16    2.1
1   A  2017-01-28  2017-03-23    6.0
2   B  2017-01-01  2017-02-10    6.0

感谢@jezrael的优雅方法!