R:基于因子或数字的聚合

时间:2014-10-06 16:01:38

标签: r aggregate

我试图聚合一些数字和因子变量的数据。如果变量是数字,我喜欢平均值。如果它是一个因素,我喜欢最常出现的价值。我已经写了以下功能,但我没有得到输出我喜欢:

meanOrMostFreq <- function(x){
    if(class(x) == 'factor'){
    tbl <- as.data.frame(table(x))
    tbl$Var1 <- as.character(tbl$Var1)
    return(tbl[tbl$Freq == max(tbl$Freq),'Var1'][1])
    }
    if(class(x) == 'numeric'){
    meanX <- mean(x, na.rm = TRUE)
    return(meanX)
    }
}

以下是我如何使用它:

df1 <- iris[1:148,]
df1$letter1 <- as.factor(rep(letters[1:4], 37))

momf <- aggregate(.~ Species, df1, FUN = function(x) meanOrMostFreq(x))

结果:

> momf
     Species Sepal.Length Sepal.Width Petal.Length Petal.Width letter1
1     setosa     5.006000    3.428000     1.462000       0.246    2.46
2 versicolor     5.936000    2.770000     4.260000       1.326    2.54
3  virginica     6.610417    2.964583     5.564583       2.025    2.50

我希望在最后一栏中获得一个实际的字母,而不是一个数字。关于我做错了什么的任何建议?

3 个答案:

答案 0 :(得分:5)

这是使用data.table

的方法
library(data.table)
setDT(df1)[ ,lapply(.SD, function(x) if(is.numeric(x)) mean(x, na.rm=TRUE) else
          names(which.max(table(x)))) , by=Species]

#         Species Sepal.Length Sepal.Width Petal.Length Petal.Width letter1
#1:     setosa     5.006000    3.428000     1.462000       0.246       a
#2: versicolor     5.936000    2.770000     4.260000       1.326       c
#3:  virginica     6.610417    2.964583     5.564583       2.025       a

答案 1 :(得分:1)

通过公式接口aggregate显然会丢失其元素的元数据;这对我有用:

> meanOrMostFreq
function(x){
    if(class(x) == 'factor'){
    return(  names(which.max(table(x))) )
    }
    if(class(x) == 'numeric'){
    meanX <- mean(x, na.rm = TRUE)
    return(meanX)
    }
}
> aggregate(df1[-5], df1[5], meanOrMostFreq)
     Species Sepal.Length Sepal.Width Petal.Length Petal.Width letter1
1     setosa     5.006000    3.428000     1.462000       0.246       a
2 versicolor     5.936000    2.770000     4.260000       1.326       c
3  virginica     6.610417    2.964583     5.564583       2.025       a

由于aggregate.formulaaggregate.data.frame存在不同的行为,这对我来说就像是一个错误。

答案 2 :(得分:1)

使用plyr包的替代方案:

ddply(df1, .(Species), function(df) {
    sapply(df, meanOrMostFreq)
})

[]的