Скользящее основанное на времени groupby () среднее для неиндексированного столбца datetime - PullRequest
0 голосов
/ 05 июля 2019

Мне нужно выяснить, выиграл ли игрок более половины своих предыдущих игр (не включая текущую игру) за последние 4,5 часа.Вариации ...rolling('4.5h')... не работают, поскольку столбец времени не является индексом и не может быть преобразован в индекс с set_index('game_t').

. Игры обозначаются столбцом gid (идентификатор игры), и'w' и 'l' указывают соответственно выигрыши и проигрыши в столбце wl.Время игры для каждого идентификатора игры хранится в game_t

У меня есть DataFrame, для которого следующее хорошее минимальное приближение:

df = pd.DataFrame({'game_t': [pd.datetime.now() - dt.timedelta(hours=n) for n in range(10)],
                    'player': [*'abacabaccb'],
                    'wl': ['w','l']*5,
                    'gid': [1,1,2,2,3,3,4,4,5,5]})
df.game_t = df.groupby('gid').game_t.transform('first')
df
#                       game_t player wl  gid
# 0 2019-07-05 15:00:23.840588      a  w    1
# 1 2019-07-05 15:00:23.840588      b  l    1
# 2 2019-07-05 13:00:23.840605      a  w    2
# 3 2019-07-05 13:00:23.840605      c  l    2
# 4 2019-07-05 11:00:23.840611      a  w    3
# 5 2019-07-05 11:00:23.840611      b  l    3
# 6 2019-07-05 09:00:23.840618      a  w    4
# 7 2019-07-05 09:00:23.840618      c  l    4
# 8 2019-07-05 07:00:23.840623      c  w    5
# 9 2019-07-05 07:00:23.840623      b  l    5

IOW, учитывая вышеизложенное, мне нужностолбец, назовите его «bta» для «лучше среднего», например так:

#                           gt player wl  gid   bta
# 0 2019-07-05 15:00:23.840588      a  w    1  True
# 1 2019-07-05 15:00:23.840588      b  l    1 False
# 2 2019-07-05 13:00:23.840605      a  w    2  True
# 3 2019-07-05 13:00:23.840605      c  l    2 False
# 4 2019-07-05 11:00:23.840611      a  w    3  True
# 5 2019-07-05 11:00:23.840611      b  l    3 False
# 6 2019-07-05 09:00:23.840618      a  w    4 False
# 7 2019-07-05 09:00:23.840618      c  l    4  True
# 8 2019-07-05 07:00:23.840623      c  w    5 False
# 9 2019-07-05 07:00:23.840623      b  l    5 False

Независимо от того, где я пытаюсь set_index('game_t'), панда настаивает на том, что индекс должен быть монотонным.Я понимаю, что столбец game_t не является монотонным в смысле «всегда возрастающий» или «всегда убывающий», поскольку он имеет дубликаты, сгруппированные индексы должны быть монотонными, так как ни один игрок не играет в данный момент более одного раза. *

Например, следующее:

df['bta'] = df.groupby('player').apply(lambda g: g.set_index('game_t').wl.eq('w').rolling('4.5h', min_periods=0).mean())

Результат:

Traceback (последний вызов был последним): .... pandas innerals stacktrace joy ...... ValueError: индекс должен быть монотонным

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

*Кроме того: разработчики панд не знают, что означает «монотонный», потому что на самом деле он означает «постоянный, или неубывающий, или не увеличивающийся»;монотонность не подразумевает ни «увеличения», ни «уменьшения».Похоже, они означают «строго возрастающие или строго убывающие».

1 Ответ

1 голос
/ 06 июля 2019

Я не вижу каких-либо проблем с вами:

  1. game_t не является индексом: установите его как индекс
  2. game_t не монотонный: сортируйте

Вот мое решение

# sort values and set index
df = df.sort_values('game_t').set_index('game_t')

# if the player wins -> for rolling
df['is_win'] = df.wl.eq('w')

# closed='left' option skip the current game
win_mean = (df.groupby('player')
              .is_win.rolling('4.5H', closed='left')
              .mean().reset_index()
           )

df = df.reset_index().merge(win_mean, on = ['game_t', 'player'])
df['bta'] = df.is_win_y.gt(0.5)

df.sort_values(['gid', 'wl'], ascending=[True, False])

дает:

                      game_t player wl  gid  is_win_x  is_win_y    bta
8 2019-07-05 15:00:23.840588      a  w    1      True       1.0   True
9 2019-07-05 15:00:23.840588      b  l    1     False       0.0  False
6 2019-07-05 13:00:23.840605      a  w    2      True       1.0   True
7 2019-07-05 13:00:23.840605      c  l    2     False       0.0  False
4 2019-07-05 11:00:23.840611      a  w    3      True       1.0   True
5 2019-07-05 11:00:23.840611      b  l    3     False       0.0  False
2 2019-07-05 09:00:23.840618      a  w    4      True       NaN  False
3 2019-07-05 09:00:23.840618      c  l    4     False       1.0   True
0 2019-07-05 07:00:23.840623      c  w    5      True       NaN  False
1 2019-07-05 07:00:23.840623      b  l    5     False       NaN  False

Вы можете опустить две колонки is_win, если хотите.

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