Найти группу последовательных дат в Pandas DataFrame - PullRequest
0 голосов
/ 20 октября 2018

Я пытаюсь получить фрагменты данных, в которых есть последовательные даты из Pandas DataFrame.Мой df выглядит следующим образом.

      DateAnalyzed           Val
1       2018-03-18      0.470253
2       2018-03-19      0.470253
3       2018-03-20      0.470253
4       2018-09-25      0.467729
5       2018-09-26      0.467729
6       2018-09-27      0.467729

В этом df я хочу получить первые 3 строки, выполнить некоторую обработку, а затем получить последние 3 строки и выполнить обработку на этом.

Я рассчитал разницу с задержкой в ​​1, применив следующий код.

df['Delta']=(df['DateAnalyzed'] - df['DateAnalyzed'].shift(1))

Но после этого я не могу понять, как получить группы последовательных строк без итерации.

1 Ответ

0 голосов
/ 20 октября 2018

Похоже, вам нужны две логические маски: одна для определения разрывов между группами, а другая для определения того, какие даты в группе в первую очередь.

Есть также одна хитрая часть, которую можно обрезатьпо примеру.Обратите внимание, что 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()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...