熊猫-分组和汇总列中具有相同值的连续行

时间:2020-01-16 22:29:16

标签: django pandas dataframe pandas-groupby aggregation

我有一个从数据库中提取的一长列日期时间范围的pandas DataFrame,每个范围都有一个标签。日期的排序方式是使一行的开始日期为前一行的结束日期。一个可行的示例在这里:

import pandas as pd

bins = [{'start': '2020-01-12 00:00:00', 'end': '2020-01-13 00:00:00', 'label': 't3'},
        {'start': '2020-01-13 00:00:00', 'end': '2020-01-13 07:00:00', 'label': 't2'},
        {'start': '2020-01-13 07:00:00', 'end': '2020-01-13 15:30:00', 'label': 't1'},
        {'start': '2020-01-13 15:30:00', 'end': '2020-01-14 00:00:00', 'label': 't2'},
        {'start': '2020-01-14 00:00:00', 'end': '2020-01-14 07:00:00', 'label': 't2'},
        {'start': '2020-01-14 07:00:00', 'end': '2020-01-14 15:30:00', 'label': 't1'},
        {'start': '2020-01-14 15:30:00', 'end': '2020-01-15 00:00:00', 'label': 't2'},
        {'start': '2020-01-15 00:00:00', 'end': '2020-01-15 07:00:00', 'label': 't2'},
        {'start': '2020-01-15 07:00:00', 'end': '2020-01-15 15:30:00', 'label': 't1'},
        {'start': '2020-01-15 15:30:00', 'end': '2020-01-16 00:00:00', 'label': 't2'},
        {'start': '2020-01-16 00:00:00', 'end': '2020-01-16 07:00:00', 'label': 't2'},
        {'start': '2020-01-16 07:00:00', 'end': '2020-01-16 15:30:00', 'label': 't1'},
        {'start': '2020-01-16 15:30:00', 'end': '2020-01-17 00:00:00', 'label': 't2'},
        {'start': '2020-01-17 00:00:00', 'end': '2020-01-17 07:00:00', 'label': 't2'},
        {'start': '2020-01-17 07:00:00', 'end': '2020-01-17 15:30:00', 'label': 't1'},
        {'start': '2020-01-17 15:30:00', 'end': '2020-01-18 00:00:00', 'label': 't2'},
        {'start': '2020-01-18 00:00:00', 'end': '2020-01-19 00:00:00', 'label': 't2'}]
bins_df = pd.DataFrame(bins)

请注意,某些标签是连续重复的,例如第四行和第五行具有相同的标签。因此,标签't2'适用于从2020-01-13 15:30:002020-01-14 07:00:00的范围。使用熊猫,如何将具有相同标签的连续行进行分组/汇总,并采用最小值start和最大值end来组合具有相同标签的连续日期范围?

1 个答案:

答案 0 :(得分:2)

首先,我们将Series.shiftSeries.cumsum结合使用,以对每个连续的label值进行分组指示。

然后我们将groupby.aggminmax一起使用。

label_groups = bins_df['label'].ne(bins_df['label'].shift()).cumsum()

df = (
    bins_df.groupby(label_groups).agg({'start':'min', 'end':'max', 'label':'first'})
           .reset_index(drop=True)
)
                 start                 end label
0  2020-01-12 00:00:00 2020-01-13 00:00:00    t3
1  2020-01-13 00:00:00 2020-01-13 07:00:00    t2
2  2020-01-13 07:00:00 2020-01-13 15:30:00    t1
3  2020-01-13 15:30:00 2020-01-14 07:00:00    t2
4  2020-01-14 07:00:00 2020-01-14 15:30:00    t1
5  2020-01-14 15:30:00 2020-01-15 07:00:00    t2
6  2020-01-15 07:00:00 2020-01-15 15:30:00    t1
7  2020-01-15 15:30:00 2020-01-16 07:00:00    t2
8  2020-01-16 07:00:00 2020-01-16 15:30:00    t1
9  2020-01-16 15:30:00 2020-01-17 07:00:00    t2
10 2020-01-17 07:00:00 2020-01-17 15:30:00    t1
11 2020-01-17 15:30:00 2020-01-19 00:00:00    t2