Pandas groupby与重叠的组/窗口

时间:2018-04-13 18:09:10

标签: python pandas

我怀疑这种用法与groupby并不兼容,所以也许我实际上要求的是一种与我想要的不同的模式。我有一个事件数据框w / timespans,并希望能够迭代/应用函数到每天的行。但如果一行在一天开始而在另一天结束,我希望该行包含在两者中。

start = pd.DatetimeIndex(start='2018-02-01 21:00:00',
                         end='2018-02-05, 21:00:00', freq='6h')
df = pd.DataFrame({'start': start.date, 'end': start.shift(1).date, 'value': 1}, 
                  columns=['start', 'end', 'value'])

         start         end  value
0   2018-02-01  2018-02-02      1
1   2018-02-02  2018-02-02      1
2   2018-02-02  2018-02-02      1
3   2018-02-02  2018-02-02      1
4   2018-02-02  2018-02-03      1
5   2018-02-03  2018-02-03      1
6   2018-02-03  2018-02-03      1
7   2018-02-03  2018-02-03      1
8   2018-02-03  2018-02-04      1
9   2018-02-04  2018-02-04      1
10  2018-02-04  2018-02-04      1
11  2018-02-04  2018-02-04      1
12  2018-02-04  2018-02-05      1
13  2018-02-05  2018-02-05      1
14  2018-02-05  2018-02-05      1
15  2018-02-05  2018-02-05      1
16  2018-02-05  2018-02-06      1

因此,第一组应包含[0, ..., 4],然后[4, ..., 8]等。实际上,事件的间隔不均匀,因此每天的长度(行数)不会超过保持不变。

我所管理的最接近的是从groupby.indices开始并操纵这些组以匹配我想要的,但这感觉非常糟糕。

{k: np.append(v[0] - 1, v) for k, v in df.groupby('start').indices.items() 
 if not (len(v) == 1 and v[0] == 0)}

{Timestamp('2018-02-02 00:00:00'): array([0, 1, 2, 3, 4]),
 Timestamp('2018-02-03 00:00:00'): array([4, 5, 6, 7, 8]),
 Timestamp('2018-02-04 00:00:00'): array([ 8,  9, 10, 11, 12]),
 Timestamp('2018-02-05 00:00:00'): array([12, 13, 14, 15, 16])}

2 个答案:

答案 0 :(得分:2)

我相信你想UPDATE B SET Col3 = CASE WHEN Total > 1 THEN Total ELSE 0 END FROM (SELECT *, Total = SUM(Volume) OVER (PARTITION BY Col1, Col2) FROM mytable) AS B; 。有很多方法可以去,例如

aggregate

def e(inp):
    return [inp.index]

>>> df.groupby('end').aggregate(e)['start']

end
2018-02-02        [[0, 1, 2, 3]]
2018-02-03        [[4, 5, 6, 7]]
2018-02-04      [[8, 9, 10, 11]]
2018-02-05    [[12, 13, 14, 15]]
2018-02-06                [[16]]
Name: start, dtype: object

现在,您可以使用这些系列,例如以下产生输出

df.groupby('start').aggregate(e)['end']
start
2018-02-01                 [[0]]
2018-02-02        [[1, 2, 3, 4]]
2018-02-03        [[5, 6, 7, 8]]
2018-02-04     [[9, 10, 11, 12]]
2018-02-05    [[13, 14, 15, 16]]
Name: end, dtype: object

答案 1 :(得分:0)

首先,我会连接startend数据,并将结果列命名为date,例如:

df_concat = pd.DataFrame(pd.concat([df.start,df.end]),columns=['date'])

然后我会创建一个索引列:

df_concat['index'] = df_concat.apply(lambda x: x.name,axis=1)

最后是groupbyapply,例如:

df_concat.groupby('date')['index'].apply(lambda x: sorted(set(x)))

输出如下:

date
2018-02-01                     [0]
2018-02-02         [0, 1, 2, 3, 4]
2018-02-03         [4, 5, 6, 7, 8]
2018-02-04      [8, 9, 10, 11, 12]
2018-02-05    [12, 13, 14, 15, 16]
2018-02-06                    [16]
Name: index, dtype: object

正如@RafaelC所说,有很多方法,这个方法是apply而不是aggregate,我不会删除相应列表中只有一个值的日期