将函数应用于R中数据框的每列内的组

时间:2013-05-06 21:41:45

标签: r lapply sapply

我想按组计算大数据帧子集中每列的平均值和标准差。

我试图理解为什么类似问题的某些答案对我不起作用;我在R还是很新,我确信有很多细微之处(而且不是那么微妙的事情!)我完全失踪了。

我有一个类似于这个的大型数据框:

mydata <- data.frame(Experiment = rep(c("E1", "E2", "E3", "E4"), each = 9), 
                     Treatment = c(rep(c("A", "B", "C"), each = 3), rep(c("A", "C", "D"), each = 3), rep(c("A", "D", "E"), each = 3), rep(c("A", "B", "D"), each = 3)), 
                     Day1 = sample(1:100, 36), 
                     Day2 = sample(1:100, 36),
                     Day3 = sample(1:150, 36),
                     Day4 = sample(50:150, 36))

我需要通过实验和治疗对数据进行子集化,例如:

testB <- mydata[(mydata[, "Experiment"] %in% c("E1", "E4")) 
            & mydata[, "Treatment"] %in% c("A", "B"), 
            c("Treatment", "Day1", "Day2", "Day4")]

然后,对于testB中的每一列,我想计算每个治疗组的平均值和标准差。

我开始尝试使用tapply(仅用一列开始),但是回过头来看看&#34; NA&#34;对于不应该在testB中的治疗组,这对于这个小数据集来说不是一个大问题,但对我的真实数据非常不满意:

>tapply(testB$Day1, testB$Treatment, mean)
   A        B        C        D        E 
70.66667 61.00000       NA       NA       NA 

我尝试从Compute mean and standard deviation by group for multiple variables in a data.frame实施解决方案。使用聚合工作:

ag <- aggregate(. ~ Treatment, testB, function(x) c(mean = mean(x), sd = sd(x)))

但我无法获得data.table解决方案。

library(data.table)
testB[, sapply(.SD, function(x) list(mean=mean(x), sd=sd(x))), by = Treatment]
testB[, c(mean = lapply(.SD, mean), sd = lapply(.SD, sd)), by = Treatment]

都给了我错误信息

Error in `[.data.frame`(testB, , c(mean = lapply(.SD, mean), sd = lapply(.SD,  : 
unused argument(s) (by = Treatment)

我做错了什么?

提前感谢帮助一个无知的初学者!

2 个答案:

答案 0 :(得分:0)

您的专栏是因素。虽然您已删除子集testB中具有处理“C”,“D”和“E”的行,但这些级别仍然存在。使用级别(testB)来查看它们。您可以在定义testB子集时使用droplevels函数,以便在不返回空因子级别的NA的情况下获取A和B的均值。

testB <- droplevels(mydata[(mydata[, "Experiment"] %in% c("E1", "E4")) 
        & mydata[, "Treatment"] %in% c("A", "B"), 
        c("Treatment", "Day1", "Day2", "Day4")]
tapply(testB$Day1,testB$Treatment,mean)
   A        B 
59.16667 66.00000 

希望这有帮助!

罗恩

答案 1 :(得分:0)

您也可以使用plyrreshape2来解决此问题;我通常更喜欢使用这些库,因为它们引入的抽象适用于更多问题,并且更清晰。

我将如何解决它:

library(plyr)
library(reshape2)
# testB from your code above

# make a "long" version of testB
longTestB <- melt(testB, id.vars="Treatment")
# then use ddply for calculating your metrics
ddply(longTestB, .(Treatment), summarize, mean=mean(value), stdev=sd(value))