Pandas GroupBy с кумулятивной суммой для смежных групп - PullRequest
1 голос
/ 08 мая 2020

Я хочу понять, сколько раз мы находимся в «Аномальном состоянии» до того, как у нас будет «Событие». Моя цель - изменить мой фрейм данных, чтобы получить следующий результат, в котором каждый раз, когда мы достигаем «события», «Группировка аномальных состояний» сбрасывается до отсчета с нуля.

Мы можем go через ряд «Аномальных состояний». Состояния »до того, как мы дойдем до« События », которое считается неудачным. (т. е. лампочка включается и выключается на несколько периодов, прежде чем окончательно погаснет, что приведет к событию).

Я написал следующий код, чтобы мои AbnormalStateGroupings увеличивались до соответствующих групп для моего анализа, который работал нормально. Однако мы хотим «сбрасывать» счетчик наших «AbnormalStates» после каждого события (например, сбоя лампочки):

dataframe['AbnormalStateGrouping'] = (dataframe['AbnormalState']!=dataframe['AbnormalState'].shift()).cumsum()

Я создал дополнительный столбец, который позволяет мне знать, в каком «событии» мы находимся. через:

dataframe['Event_Or_Not'].cumsum() #I have a boolean representation of the Event Column represented and we use .cumsum() to get the relevant groupings (i.e. 1st Event, 2nd Event, 3rd Event etc.)

Я уже близко подходил к этому, используя следующее:

eventOrNot = dataframe['Event'].eq(0)
eventMask = (eventOrNot.ne(eventOrNot.shift())&eventOrNot).cumsum()
dataframe['AbnormalStatePerEvent'] =dataframe.groupby(['Event',eventMask]).cumcount().add(1)

Однако это не дало мне желаемого результата, который мне нужен (как показано ниже ). Однако я думаю, что я близок - может ли кто-нибудь посоветовать, что я могу попытаться сделать дальше, чтобы при каждом выходе из строя лампочки счетчик аномальных состояний сбрасывался и начинал подсчет количества аномальных состояний, через которые мы прошли до следующего выхода из строя лампочки?

Состояние, к которому я хочу перейти с помощью AbnormalStateGrouping

Вы могли бы заметить, что при обнаружении «события» счетчик аномального состояния сбрасывается до 1, а затем начинает отсчет снова.

End State

Текущее состояние фрейма данных

Current State of Dataframe

Ниже прилагается источник данных: https://filebin.net/ctjwk7p3gulmbgkn

1 Ответ

2 голосов
/ 08 мая 2020

Я предполагаю, что ваш исходный DataFrame имеет только Дата / Время (либо строка , либо datetime ), Событие ( строка ) и AbnormalState ( int ) столбцы.

Чтобы вычислить столбец группировки, запустите:

dataframe['AbnormalStateGrouping'] = dataframe.groupby(
    dataframe['Event'][::-1].notnull().cumsum()).AbnormalState\
    .apply(lambda grp: (grp != grp.shift()).cumsum())

Результат, для исходных исходных данных, представленных в виде изображения, это:

           Date/Time  Event  AbnormalState  AbnormalStateGrouping
0   2018-01-01 01:00    NaN              0                      1
1   2018-01-01 02:00    NaN              0                      1
2   2018-01-01 03:00    NaN              1                      2
3   2018-01-01 04:00    NaN              1                      2
4   2018-01-01 05:00    NaN              0                      3
5   2018-01-01 06:00    NaN              0                      3
6   2018-01-01 07:00    NaN              0                      3
7   2018-01-01 08:00    NaN              1                      4
8   2018-01-01 09:00    NaN              1                      4
9   2018-01-01 10:00    NaN              0                      5
10  2018-01-01 11:00    NaN              0                      5
11  2018-01-01 12:00    NaN              0                      5
12  2018-01-01 13:00    NaN              1                      6
13  2018-01-01 14:00    NaN              1                      6
14  2018-01-01 15:00    NaN              0                      7
15  2018-01-01 16:00  Event              0                      7
16  2018-01-01 17:00    NaN              1                      1
17  2018-01-01 18:00    NaN              1                      1
18  2018-01-01 19:00    NaN              0                      2
19  2018-01-01 20:00    NaN              0                      2

Обратите внимание на способ группировки:

dataframe['Event'][::-1].notnull().cumsum()

Из-за [:: - 1] , cumsum функция вычисляется от последней строки до первой. Таким образом:

  • строки с часами 01: 00 через 16: 00 находятся в группе 1 ,
  • оставшиеся строки (час 17: 00 через 20: 00 ) находятся в группе 0 .

Затем до AbnormalState , отдельно для каждой группы применяется лямбда-функция, поэтому каждая совокупная сумма начинается с 1 только в каждой группе (после каждого Event ) .

Редактировать после комментария от 22: 18: 12Z

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

dataframe['Event'].notnull().cumsum()

затем:

  • строк с индексом 0 через 14 (перед строкой с Event ) имеет эту сумму == 0 ,
  • строка с индексом 15 , а следующие строки имеют эту сумму == 1 .

Попробуйте обе версии, без и с [:: - 1] .

* 10 94 * Результат в обычном порядке (без [:: - 1] ) таков:
  • Событие строка находится в той же группе с после строк,
  • , поэтому сброс происходит только в этой строке.

Чтобы проверить весь результат, запустите мой код без [:: - 1] , и вы увидите, что конечная часть результата содержит:

             Date/Time  Event  AbnormalState  AbnormalStateGrouping
14 2018-01-01 15:00:00    NaN              0                      7
15 2018-01-01 16:00:00  Event              0                      1
16 2018-01-01 17:00:00    NaN              1                      2
17 2018-01-01 18:00:00    NaN              1                      2
18 2018-01-01 19:00:00    NaN              0                      3
19 2018-01-01 20:00:00    NaN              0                      3

, так что строка Event должна иметь AbnormalStateGrouping == 1 .

Но вы хотите, чтобы эта строка имела AbnormalStateGrouping в последовательности предыдущих состояний группировки (в данном случае 7 ), и сброс должен происходить из следующей строки.

Таким образом, строка Event должна быть в той же группе с предшествующей строк, каков результат моего кода.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...