我的数据框:
df<-data.frame(ID = rep(c("no","bo", "fo", "to"), each = 3), matrix(sample(60), ncol = 5))
names(df) <- c("ID", letters[1:5])
我计算了每个观察组的平均值,我使用了这个:
df.n.mean <- aggregate(. ~ ID, df, function(x) c(mean = mean(x)))
我想知道我是否可以使用apply方法而不是聚合方法。这会加快这个过程吗?
答案 0 :(得分:3)
我认为aggregate()
的最快替代是使用 data.table
library(data.table)
( dt <- setDT(df)[, lapply(.SD, mean), by = ID] )
# ID a b c d e
# 1: no 25.000000 26.00000 24.66667 39.00000 39.66667
# 2: bo 40.666667 25.33333 31.33333 37.00000 19.33333
# 3: fo 5.333333 28.00000 53.33333 11.66667 29.33333
# 4: to 30.666667 47.33333 27.00000 41.33333 28.00000
对于行减法,我们可以编写一个函数并将其与Map()
一起使用。
f <- function(x, y) {
dt[ID == x, -1, with = FALSE] - dt[ID == y, -1, with = FALSE]
}
rbindlist(Map(f, c("bo", "fo", "to", "to"), c("no", "no", "bo", "fo")))
# a b c d e
# 1: 15.66667 -0.6666667 6.666667 -2.000000 -20.333333
# 2: -19.66667 2.0000000 28.666667 -27.333333 -10.333333
# 3: -10.00000 22.0000000 -4.333333 4.333333 8.666667
# 4: 25.33333 19.3333333 -26.333333 29.666667 -1.333333
可能有更好的方法来编写函数f()
以及 data.table 中的最后一次调用,如果可能的话,我会尝试改进它。请注意,由于您在未设置种子的情况下使用sample()
,此输出将与您的输出不匹配。
另一种可能性是做以下事情。这将为您提供所需的行名称。
A <- c("bo", "fo", "to", "to")
B <- c("no", "no", "bo", "fo")
df2 <- as.data.frame(rbindlist(Map(f, A, B)))
rownames(df2) <- paste(A, B, sep = "-")
df2
# a b c d e
# bo-no 15.66667 -0.6666667 6.666667 -2.000000 -20.333333
# fo-no -19.66667 2.0000000 28.666667 -27.333333 -10.333333
# to-bo -10.00000 22.0000000 -4.333333 4.333333 8.666667
# to-fo 25.33333 19.3333333 -26.333333 29.666667 -1.333333
答案 1 :(得分:2)
您可以使用包dplyr
和函数summarise_each
来替换aggregate
:
library(dplyr)
newdf <- df %>% group_by(ID) %>% summarise_each(funs(mean))
给你
ID a b c d e
(fctr) (dbl) (dbl) (dbl) (dbl) (dbl)
1 bo 48.66667 32.00000 22.66667 33.33333 33.33333
2 fo 19.33333 15.00000 36.66667 25.33333 23.00000
3 no 35.00000 22.33333 37.00000 20.66667 31.00000
4 to 41.33333 39.00000 20.33333 37.00000 37.00000
这个包通常很快。但是,我不确定你问题的第二部分是否符合理查德的建议。