R Dataframe 按组滚动测量

R Dataframe Rolling Measures by Group

我有一个数据框如下所示(真实数据有更多人):

Year   Player    Club
2005   Phelan    Chicago Fire 
2007   Phelan    Boston Pant
2008   Phelan    Boston Pant
2010   Phelan    Chicago Fire  
2002   John      New York Jet
2006   John      New York Jet
2007   John      Atlanta Elephant
2009   John      Los Angeles Eagle

我想计算每一行(年)的球员水平衡量标准(计数),以获取一个人在该点之前经历的俱乐部的加权数量。公式为(经验长度1/到该点的总年数)^2+(经验长度2/到该点的总年数)^2+......

以下是 Phelan 的理想输出。例如,他的第一行的“计数”是 1,因为这是他在数据中的第一年,并且 (1/1)^2=1。对于他的第二行,包括到目前为止的三年(2005、2006、2007),count=(1/3)^2+(2/3)=0.56(假设 2006 年缺少数据,Phelan 还留在芝加哥大火)。对于他的第三行,count=(2/4)^2+(2/4)^2=0.5。对于他的第四行,count=(3/6)^2+(3/6)^2=0.5(假设在缺少数据的 2009 年,Phelan 也留在了 Boston Pant)。

Year   Player    Club            Count
2005   Phelan    Chicago Fire    1
2007   Phelan    Boston Pant     0.56
2008   Phelan    Boston Pant     0.5
2010   Phelan    Chicago Fire    0.5

这有点令人费解,但我认为它可以满足您的需求。

使用data.table:

library(data.table)
library(zoo)          # for na.locf(...)
##
expand.df <- setDT(df)[, .(Year=min(Year):max(Year)), by=.(Player)]
expand.df[df, Club:=i.Club, on=.(Player, Year)]
expand.df[, Club:=na.locf(Club)]
expand.df[, cuml.exp:=1:.N, by=.(Player)]
expand.df <- expand.df[expand.df[, .(Player, cuml.exp)], on=.(Player, cuml.exp <= cuml.exp)]
expand.df <- expand.df[, .(Year=max(Year), club.exp=sum(sapply(unique(Club), \(x) sum(Club==x)^2))), by=.(Player, cuml.exp)]
expand.df[, score:=club.exp/cuml.exp^2]
result <- expand.df[df, on=.(Player, Year), nomatch=NULL]
result[, .(Player, Year, Club, cuml.exp, club.exp, score)]
##    Player Year              Club cuml.exp club.exp     score
## 1: Phelan 2005      Chicago Fire        1        1 1.0000000
## 2: Phelan 2007       Boston Pant        3        5 0.5555556
## 3: Phelan 2008       Boston Pant        4        8 0.5000000
## 4: Phelan 2010      Chicago Fire        6       18 0.5000000
## 5:   John 2002      New York Jet        1        1 1.0000000
## 6:   John 2006      New York Jet        5       25 1.0000000
## 7:   John 2007  Atlanta Elephant        6       26 0.7222222
## 8:   John 2009 Los Angeles Eagle        8       30 0.4687500

因此,这会扩展您的 df 以包括每个球员每年一行,然后在适当的年份重新加入俱乐部,然后根据您的描述填补空白。然后我们计算每个玩家的累计经验年数。

下一位是复杂的部分:我们需要进一步扩展,以便对于 player 和 cuml.exp 的每个组合,我们拥有到该点为止的所有行。 join on=.(Player, cuml.exp <= cuml.exp) 就是这样做的。然后我们可以按球员统计每个俱乐部的实例数,cuml.exp得到你得分的分子。

然后我们计算分数,去掉多余的年份和多余的列。

请注意,这假设您拥有 R 4.1+。如果不是,请将 \(x)... 替换为 function(x)....