3

我有一个沿着这些方向的数据集:

df<-data.frame(sp=c(100, 100, 100, 101, 101, 101, 102, 102, 102),
type=c("C","C","C","H","H","H","C","C","C"),
country=c("A", "A", "A", "B", "B", "B", "C", "C", "C"),
vals=c(1,2,3,4,5,6,7,8,9)
)

我想聚合 df$vals 并将其他变量也通过

目前我正在这样做:

multi.func<- function(x){
c(
n = length(x),
min = min(x, na.rm=TRUE),
max = max(x, na.rm=TRUE),
mean = mean(x, na.rm=TRUE)
)}

aggVals<-as.data.frame(do.call(rbind, by(df$vals, df$sp, FUN=multi.func, simplify=TRUE)))
aggVals$sp<-row.names(aggVals)

aggDescrip<-aggregate(cbind(as.character(type), as.character(country)) ~ sp, data=df, FUN=unique)

result<-merge(aggDescrip,aggVals)

这工作得很好,但我想知道是否有更简单的方法。

谢谢

4

2 回答 2

3

也许你应该看看这个data.table包。

library(data.table)
DT <- data.table(df, key="sp")
DT[, list(type = unique(as.character(type)), 
          country = unique(as.character(country)), 
          n = .N, min = min(vals), max = max(vals), 
          mean = mean(vals)), by=key(DT)]
#     sp type country n min max mean
# 1: 100    C       A 3   1   3    2
# 2: 101    H       B 3   4   6    5
# 3: 102    C       C 3   7   9    8

如果您想坚持使用基本 R,这里是另一种可能有用的方法(尽管aggregate可能更常见):

unique(within(df, {
    mean <- ave(vals, sp, FUN=mean)
    max <- ave(vals, sp, FUN=max)
    min <- ave(vals, sp, FUN=min)
    n <- ave(vals, sp, FUN=length)
    rm(vals)
}))
#    sp type country n min max mean
# 1 100    C       A 3   1   3    2
# 4 101    H       B 3   4   6    5
# 7 102    C       C 3   7   9    8

更新:您最初尝试的变化

如果可能的话,我建议坚持使用data.table,因为生成的代码很容易理解并且聚合过程很快。

但是,通过一些修改,您可以拥有(又一种)更直接的基本 R 方法。

首先,修改您的函数,以便使用而不是c()使用data.frame。此外,添加一个参数来指定需要聚合的列。

multi.func <- function(x, value_column) {
    data.frame(
        n = length(x[[value_column]]),
        min = min(x[[value_column]], na.rm=TRUE),
        max = max(x[[value_column]], na.rm=TRUE),
        mean = mean(x[[value_column]], na.rm=TRUE))
}

其次,lapply在您的数据集split上使用您的分组变量,merge将输出与您的原始数据集一起使用,然后返回unique值。

unique(merge(df[-4], 
             do.call(rbind, lapply(split(df, df$sp), 
                                   multi.func, value_column = "vals")),
             by.x = "sp", by.y = "row.names"))
于 2012-12-17T15:51:10.623 回答
2

仅使用aggregate

result <- aggregate(vals ~ type + sp + country, df, 
    function(x) c(length(x), min(x), max(x), mean(x))
)

result
  type  sp country vals.1 vals.2 vals.3 vals.4
1    C 100       A      3      1      3      2
2    H 101       B      3      4      6      5
3    C 102       C      3      7      9      8

colnames(result)
[1] "type"    "sp"      "country" "vals"  

以上似乎创建了一个奇怪的“多值”列。但从包summaryBydoBy类似于aggregate但将允许具有多列的输出:

library(doBy)
result <- summaryBy(vals ~ type + sp + country, df, 
    FUN=function(x) c(n=length(x), min=min(x), max=max(x), mean=mean(x))
)

result
  type  sp country vals.n vals.min vals.max vals.mean
1    C 100       A      3        1        3         2
2    C 102       C      3        7        9         8
3    H 101       B      3        4        6         5

colnames(result)
[1] "type"      "sp"        "country"   "vals.n"    "vals.min"  "vals.max" 
[7] "vals.mean"
于 2012-12-17T15:10:18.227 回答