我正在尝试学习一些本来应该在SQL窗口函数中进行的熊猫。
假设我有以下数据框,该数据框显示了不同球员之前的比赛以及每场比赛杀死了多少人。
date player kills
2019-01-01 a 15
2019-01-02 b 20
2019-01-03 a 10
2019-03-04 a 20
在下面的代码中,我设法创建了一个groupby,其中只显示以前的击杀总和(玩家击杀的总和,不包括他在当前行的游戏中获得的击杀)。
df['sum_kills'] = df.groupby('player')['kills'].transform(lambda x: x.cumsum().shift())
这将创建以下值:
date player kills sum_kills
2019-01-01 a 15 NaN
2019-01-02 b 20 NaN
2019-01-03 a 10 15
2019-03-04 a 20 25
但是,我理想中想要的是在组合值中包括filter / where子句的选项。假设我只想获取前30天(1个月)的总和。然后,我的新数据框应如下所示:
date player kills sum_kills
2019-01-01 a 15 NaN
2019-01-02 b 20 NaN
2019-01-03 a 10 15
2019-03-04 a 20 NaN
最后一行将提供零的summed_kills,因为在过去的一个月中没有玩过玩家a的游戏。这有可能吗?
答案 0 :(得分:0)
我认为您在使用groupby
和transform
时有些紧张。如here所述,transform
在单个序列上进行操作,因此您无法访问其他列的数据。
groupby
和apply
似乎也不是正确的方法,因为预期自定义函数将返回groupby
传递的组的汇总结果,但是您希望每一行都有不同的结果
因此,我建议的最佳解决方案是不使用apply
的{{1}},并在自定义函数中自行执行所有选择:
groupy
这将返回:
def killcount(x, data, timewin):
"""count the player's kills in a time window before the time of current row.
x: dataframe row
data: full dataframe
timewin: a pandas.Timedelta
"""
return data.loc[(data['date'] < x['date']) #select dates preceding current row
& (data['date'] >= x['date']-timewin) #select dates in the timewin
& (data['player'] == x['player'])]['kills'].sum() #select rows with same player
df['sum_kills'] = df.apply(lambda r : killcount(r, df, pd.Timedelta(30, 'D')), axis=1)
如果尚未完成操作,请记住使用pandas.to_datetime将 date player kills sum_kills
0 2019-01-01 a 15 0
1 2019-01-02 b 20 0
2 2019-01-03 a 10 15
3 2019-03-04 a 20 0
列解析为日期时间类型,否则无法执行日期比较。