我是plyr(和R)的新手并且正在寻求一些帮助以便开始。使用棒球数据集作为一个例子,我如何计算联盟和球队(lg和球队)在“击球”中的同比变化(同比)?
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)
}
没有成功,我使用以下代码尝试返回yoy更改。
df2 <- ddply(df1, .(lg, team), yoy.func)
任何指导都应该受到赞赏。
由于
答案 0 :(得分: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
答案 1 :(得分: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