Нам понадобится способ сгруппировать их вместе, если они являются частью блока. Во-первых, давайте найдем все моменты, когда начало не совпадает с концом следующего элемента. Эта серия имеет значение True, если элемент является первым в блоке, и false в противном случае.
temp = (dat['start'] != dat['end'].shift(1))
Это выглядит так:
0 True
1 False
2 False
3 True
4 False
5 True
6 True
7 False
Затем мы можем взять кумулятивную сумму. Когда вы сделаете это для True / False, True добавит 1 к сумме, а False не изменит ее. Это полезно, потому что тогда мы получаем группировку - каждый блок, который вы хотели объединить, изначально имеет свой собственный номер, связанный с ним.
groups = temp.cumsum()
выглядит так:
0 1
1 1
2 1
3 2
4 2
5 3
6 4
7 4
Теперь мы почти у цели. Для каждой группы вы хотите получить минимальное начало, максимальное значение и объединить весь текст.
datg = dat.groupby(groups)
out = pd.DataFrame({
'task': datg['task'].apply(' '.join),
'start': datg['start'].min(),
'end': datg['end'].max(),
})
Это дает окончательный результат: в одном месте:
temp = (dat['start'] != dat['end'].shift(1))
groups = temp.cumsum()
datg = dat.groupby(groups)
out = pd.DataFrame({
'task': datg['task'].apply(' '.join),
'start': datg['start'].min(),
'end': datg['end'].max(),
})