Похоже, вам нужны две логические маски: одна для определения разрывов между группами, а другая для определения того, какие даты в группе в первую очередь.
Есть также одна хитрая часть, которую можно обрезатьпо примеру.Обратите внимание, что df
ниже содержит добавленную строку, которая не имеет последовательных дат до или после нее.
>>> df
DateAnalyzed Val
1 2018-03-18 0.470253
2 2018-03-19 0.470253
3 2018-03-20 0.470253
4 2017-01-20 0.485949 # < watch out for this
5 2018-09-25 0.467729
6 2018-09-26 0.467729
7 2018-09-27 0.467729
>>> df.dtypes
DateAnalyzed datetime64[ns]
Val float64
dtype: object
В ответе ниже предполагается, что вы хотите полностью игнорировать 2017-01-20
, не обрабатывая его.(См. Конец ответа для решения, если вы хотите обработать эту дату.)
Первое:
>>> dt = df['DateAnalyzed']
>>> day = pd.Timedelta('1d')
>>> in_block = ((dt - dt.shift(-1)).abs() == day) | (dt.diff() == day)
>>> in_block
1 True
2 True
3 True
4 False
5 True
6 True
7 True
Name: DateAnalyzed, dtype: bool
Теперь in_block
сообщит вам, какие даты находятся в "последовательном""блок, но он не скажет вам, к каким группам относится каждая дата.
Следующим шагом будет получение самих группировок:
>>> filt = df.loc[in_block]
>>> breaks = filt['DateAnalyzed'].diff() != day
>>> groups = breaks.cumsum()
>>> groups
1 1
2 1
3 1
5 2
6 2
7 2
Name: DateAnalyzed, dtype: int64
Затем вы можете позвонить df.groupby(groups)
сВаша операция выбора.
>>> for _, frame in filt.groupby(groups):
... print(frame, end='\n\n')
...
DateAnalyzed Val
1 2018-03-18 0.470253
2 2018-03-19 0.470253
3 2018-03-20 0.470253
DateAnalyzed Val
5 2018-09-25 0.467729
6 2018-09-26 0.467729
7 2018-09-27 0.467729
Чтобы включить это обратно в df
, присвойте ему, и отдельные даты будут NaN
:
>>> df['groups'] = groups
>>> df
DateAnalyzed Val groups
1 2018-03-18 0.470253 1.0
2 2018-03-19 0.470253 1.0
3 2018-03-20 0.470253 1.0
4 2017-01-20 0.485949 NaN
5 2018-09-25 0.467729 2.0
6 2018-09-26 0.467729 2.0
7 2018-09-27 0.467729 2.0
Если выесли вы захотите включить «одинокую» дату, все станет немного проще:
dt = df['DateAnalyzed']
day = pd.Timedelta('1d')
in_block = ((dt - dt.shift(-1)).abs() == day) | (dt.diff() == day)
breaks = dt.diff() != day
groups = breaks.cumsum()