基于滚动时间的groupby()表示非索引日期时间列

时间:2019-07-05 20:23:17

标签: python pandas pandas-groupby

我需要确定玩家在过去4.5个小时内是否赢得了超过之前游戏的一半(不包括当前游戏)。 ...rolling('4.5h')...的变体不起作用,因为时间列不是索引,并且不能用set_index('game_t')变成一个。

游戏在gid栏中由wl(游戏ID)列表示,“ w”和“ l”分别表示获胜和失败。每个游戏ID的游戏时间都存储在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'),pandas都坚持认为索引必须是单调的。我知道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内部构件stacktrace喜悦...   ... ValueError:索引必须是单调的

无论如何,我以前的尝试都没有任何价值,因为它们要么给出了错误的答案,要么引发了典型的“您无法从此处到达那里,而且即使尝试(尽管您可能已经说过apply了,但您是否尝试过使用transform?)“熊猫错误消息。

*顺便说一句:大熊猫开发者不知道“单调”的含义,因为它实际上是“恒定的,不变的,不变的或不变的”。单调性既不表示“增加”也不表示“减少”。他们似乎意味着“严格增加或严格减少”。

1 个答案:

答案 0 :(得分:1)

我认为您的任何问题都不是问题:

  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