我需要确定玩家在过去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
?)“熊猫错误消息。
*顺便说一句:大熊猫开发者不知道“单调”的含义,因为它实际上是“恒定的,不变的,不变的或不变的”。单调性既不表示“增加”也不表示“减少”。他们似乎意味着“严格增加或严格减少”。
答案 0 :(得分:1)
我认为您的任何问题都不是问题:
game_t
不是索引:将其设置为索引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
。