Увеличение количества, когда условие выполняется в пределах панд GroupBy - PullRequest
0 голосов
/ 20 января 2019

Как подсчитать количество многоколонок (вещь, cond = 1) вхождения событий перед каждым (вещь, cond = любая) событие?


(Это могут быть выигрыши в покер за игроком, эпизоды депрессии у пациента и т. Д.) Например, строка index == 3 ниже содержит пару (thing, cond) = (c,2) и показывает число предыдущих (c,1) вхождений, что правильно (но вручную) отображается в столбце priors как 0. Я заинтересован в создании синтетического столбца с количеством предыдущих (вещь, 1) событий для каждой пары (вещь, событие) в моих данных. Мои данные монотонно увеличиваются во времени. Естественный индекс в silly DataFrame может быть взят в качестве логических тиков, если это помогает. (: Это действительно не так.)

Для удобства ниже приведен код моего теста DataFrame и сгенерированный вручную столбец priors, который я не могу заставить панды генерировать с пользой, независимо от того, какие комбинации groupby, cumsum, shift , where и т. Д. Я пытаюсь. Я гуглил и ломал свой мозг в течение нескольких дней. Нет, так что ответы, похоже, отвечают всем требованиям. Ключ к чтению столбца априора заключается в том, что в его записях говорится что-то вроде: «До этого (a, 1) или (a, 2) события было 2 (a, 1) события».

[In]:
import pandas as pd
silly = pd.DataFrame({'thing': ['a','b','a','c','b','c','c','a','a','b','c','a'], "cond": [1,2,1,2,1,2,1,2,1,2,1,2]})
silly['priors'] = pd.Series([0,0,1,0,0,0,0,2,2,1,1,3])
silly

[Out]:
silly
   thing  cond  priors
0      a     1       0
1      b     2       0
2      a     1       1
3      c     2       0
4      b     1       0
5      c     2       0
6      c     1       0
7      a     2       2
8      a     1       2
9      b     2       1
10     c     1       1
11     a     2       3

Самое близкое, что я пришел, это:

silly
[In]:
silly['priors_inc'] = silly[['thing', 'cond']].where(silly['cond'] == 1).groupby('thing').cumsum() - 1

[Out]:

silly
   thing  cond  priors  priors_inc
0      a     1       0         0.0
1      b     2       0         NaN
2      a     1       1         1.0
3      c     2       0         NaN
4      b     1       0         0.0
5      c     2       0         NaN
6      c     1       0         0.0
7      a     2       2         NaN
8      a     1       2         2.0
9      b     2       1         NaN
10     c     1       1         1.0
11     a     2       3         NaN

Обратите внимание, что значения, представленные в столбце неполных априорных значений , являются правильными , но не все требуемые данные имеются.

Пожалуйста, если это вообще возможно, воздержитесь от любых "пифоновских" ответов. В то время как мои реальные данные невелики по сравнению с большинством проблем ML, я хочу научиться пандам правильно, а не игрушечным способам с петлями Python или хитростью itertools, которые я уже видел слишком много. Заранее спасибо! (И я прошу прощения за стену текста!)

1 Ответ

0 голосов
/ 20 января 2019

Вам нужно

  1. Совокупный счет, где каждый «конд» равен 1
  2. Сделайте это для каждой "вещи"
  3. Убедитесь, что счетчик shift отредактирован на 1.

Вы можете сделать это, используя groupby, cumsum и shift:

(df.cond.eq(1)
   .groupby(df.thing)
   .apply(lambda x: x.cumsum().shift())
   .fillna(0, downcast='infer'))

0     0
1     0
2     1
3     0
4     0
5     0
6     0
7     2
8     2
9     1
10    1
11    3
Name: cond, dtype: int64

Другой способ избежать apply состоит в том, чтобы связать два вызова groupby - один выполняет сдвиг, другой выполняет суммирование.

(df.cond.eq(1)
   .groupby(df.thing)
   .cumsum()
   .groupby(df.thing)
   .shift()
   .fillna(0, downcast='infer'))

0     0
1     0
2     1
3     0
4     0
5     0
6     0
7     2
8     2
9     1
10    1
11    3
Name: cond, dtype: int64
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...