5

我是 plyr(和 R)的新手,正在寻找一些帮助来开始。以棒球数据集为例,我如何计算联赛和球队(lg 和球队)“at batts”的同比(同比)变化?

library(plyr)
df1 <- aggregate(ab~year+lg+team, FUN=sum, data=baseball)

在进行了一些汇总以简化数据名声后,数据如下所示:

head(df1)

  year lg team   ab
  1884 UA  ALT  108
  1997 AL  ANA 1703
  1998 AL  ANA 1502
  1999 AL  ANA  660
  2000 AL  ANA   85
  2001 AL  ANA  219

我想以这样的方式结束

  year lg team   ab yoy
  1997 AL  ANA 1703  NA
  1998 AL  ANA 1502  -201
  1999 AL  ANA  660  -842
  2000 AL  ANA   85  -575
  2001 AL  ANA  219  134

我首先编写了以下函数,我认为这是错误的:

yoy.func <- function(df) {
  lag <- c(df$ab[-1],0)
  cur <- c(df$ab[1],0)
  df$yoy <- cur -lag
  return(df)
}

没有成功,我使用以下代码尝试返回同比变化。

df2 <- ddply(df1, .(lg, team), yoy.func)

任何指导将不胜感激。

谢谢

4

2 回答 2

6

我知道您要求提供特定于“plyr”的解决方案,但为了分享,这里是基本 R 中的另一种方法。在我看来,我发现基本 R 方法就像“可读”一样。而且,至少在这种特殊情况下,它要快得多!

output <- within(df1, {
  yoy <- ave(ab, team, lg, FUN = function(x) c(NA, diff(x)))
})
head(output)
#   year lg team   ab  yoy
# 1 1884 UA  ALT  108   NA
# 2 1997 AL  ANA 1703   NA
# 3 1998 AL  ANA 1502 -201
# 4 1999 AL  ANA  660 -842
# 5 2000 AL  ANA   85 -575
# 6 2001 AL  ANA  219  134

library(rbenchmark)

benchmark(DDPLY = {
  ddply(df1, .(team, lg), mutate ,
        yoy = c(NA, diff(ab)))
}, WITHIN = {
  within(df1, {
    yoy <- ave(ab, team, lg, FUN = function(x) c(NA, diff(x)))
  })
}, columns = c("test", "replications", "elapsed", 
               "relative", "user.self"))
#     test replications elapsed relative user.self
# 1  DDPLY          100  10.675    4.974    10.609
# 2 WITHIN          100   2.146    1.000     2.128

更新:data.table

如果您的数据非常大,请查看data.table. 即使使用此示例,您也会发现相对而言有很好的加速。此外,语法非常紧凑,在我看来,易于阅读。

library(plyr)
df1 <- aggregate(ab~year+lg+team, FUN=sum, data=baseball)
library(data.table)
DT <- data.table(df1)
DT
#       year lg team   ab
#    1: 1884 UA  ALT  108
#    2: 1997 AL  ANA 1703
#    3: 1998 AL  ANA 1502
#    4: 1999 AL  ANA  660
#    5: 2000 AL  ANA   85
#   ---                  
# 2523: 1895 NL  WSN  839
# 2524: 1896 NL  WSN  982
# 2525: 1897 NL  WSN 1426
# 2526: 1898 NL  WSN 1736
# 2527: 1899 NL  WSN  787

现在,看看这个简洁的解决方案:

DT[, yoy := c(NA, diff(ab)), by = "team,lg"]
DT
#       year lg team   ab  yoy
#    1: 1884 UA  ALT  108   NA
#    2: 1997 AL  ANA 1703   NA
#    3: 1998 AL  ANA 1502 -201
#    4: 1999 AL  ANA  660 -842
#    5: 2000 AL  ANA   85 -575
#   ---                       
# 2523: 1895 NL  WSN  839  290
# 2524: 1896 NL  WSN  982  143
# 2525: 1897 NL  WSN 1426  444
# 2526: 1898 NL  WSN 1736  310
# 2527: 1899 NL  WSN  787 -949
于 2013-01-30T05:19:03.573 回答
5

如何使用 diff():

df <- read.table(header = TRUE, text = '  year lg team   ab
  1884 UA  ALT  108
  1997 AL  ANA 1703
  1998 AL  ANA 1502
  1999 AL  ANA  660
  2000 AL  ANA   85
  2001 AL  ANA  219')
require(plyr)
ddply(df, .(team, lg), mutate ,
      yoy = c(NA, diff(ab)))
#   year lg team   ab  yoy
1 1884 UA  ALT  108   NA
2 1997 AL  ANA 1703   NA
3 1998 AL  ANA 1502 -201
4 1999 AL  ANA  660 -842
5 2000 AL  ANA   85 -575
6 2001 AL  ANA  219  134
于 2013-01-29T20:05:00.427 回答