65

我知道我可以在聚合数据后 *re*name 列:

blubb <- aggregate(dat$two ~ dat$one, ...)
colnames(blubb) <- c("One", "Two")

没有错。但是有没有办法一次性聚合和命名列?有点像:

blubb <- aggregate( ... , cols = c("One", "Two"))

以某种方式捕获原始列名并这样做会特别好(并且防错字):

blubb <- aggregate( ... , cols = c(name_of_dat$one, name_of_dat$two."_Mean"))
4

4 回答 4

85

您可以使用setNames如下:

blubb <- setNames(aggregate(dat$two ~ dat$one, ...), c("One", "Two"))

或者,您可以绕过巧妙的公式方法,并使用如下语法:

blubb <- aggregate(list(One = dat$one), list(Two = dat$two), ...)

更新

此更新只是帮助您开始自行获取解决方案。

如果您检查 的代码stats:::aggregate.formula,您将在最后看到以下几行:

if (is.matrix(mf[[1L]])) {
    lhs <- as.data.frame(mf[[1L]])
    names(lhs) <- as.character(m[[2L]][[2L]])[-1L]
    aggregate.data.frame(lhs, mf[-1L], FUN = FUN, ...)
}
else aggregate.data.frame(mf[1L], mf[-1L], FUN = FUN, ...)

如果您只想将函数名称附加到聚合的变量中,也许您可​​以将其更改为:

if (is.matrix(mf[[1L]])) {
  lhs <- as.data.frame(mf[[1L]])
  names(lhs) <- as.character(m[[2L]][[2L]])[-1L]
  myOut <- aggregate.data.frame(lhs, mf[-1L], FUN = FUN, ...)
  colnames(myOut) <- c(names(mf[-1L]), 
                       paste(names(lhs), deparse(substitute(FUN)), sep = "."))
}
else {
  myOut <- aggregate.data.frame(mf[1L], mf[-1L], FUN = FUN, ...)
  colnames(myOut) <- c(names(mf[-1L]), 
                       paste(strsplit(gsub("cbind\\(|\\)|\\s", "", 
                                           names(mf[1L])), ",")[[1]],
                             deparse(substitute(FUN)), sep = "."))
} 
myOut

FUN这基本上捕获了使用输入的值deparse(substitute(FUN)),因此您可以修改函数以接受自定义后缀,甚至可能是后缀向量。这可能可以通过一些工作来改进,但我不会这样做!

这是应用此概念的要点,创建了一个名为“myAgg”的函数。

以下是结果列名的一些示例输出:

> names(myAgg(weight ~ feed, data = chickwts, mean))
[1] "feed"        "weight.mean"
> names(myAgg(breaks ~ wool + tension, data = warpbreaks, sum))
[1] "wool"       "tension"    "breaks.sum"
> names(myAgg(weight ~ feed, data = chickwts, FUN = function(x) mean(x^2)))
[1] "feed"                         "weight.function(x) mean(x^2)"

请注意,只有聚合变量名称会更改。但也要注意,如果你使用自定义函数,你最终会得到一个非常奇怪的列名!

于 2013-03-09T09:34:05.067 回答
13

你的第一个问题的答案是肯定的。您当然可以在聚合函数中包含列名。使用上面示例中的名称:

blubb <- aggregate(dat,list(One=dat$One,Two=dat$Two),sum)

我喜欢关于可能自动提取原始列名的部分。如果我弄清楚了,我会发布它。

于 2013-09-18T08:49:47.543 回答
5

如果您更喜欢编写聚合,因为formula文档显示了cbind. 并cbind允许您命名它的参数,由aggregate.

aggregate(cbind(SLength = Sepal.Length) ~ cbind(Type = Species),
  data = iris, mean)
#  Type SLength
#1    1   5.006
#2    2   5.936
#3    3   6.588

cbind取而代之factors的是他们的内部代码。为避免这种情况,您可以使用:

aggregate(SLength ~ Type, with(iris, data.frame(SLength = Sepal.Length,
  Type = Species)), mean)
#        Type SLength
#1     setosa   5.006
#2 versicolor   5.936
#3  virginica   6.588

或者

with(iris, aggregate(data.frame(SLength = Sepal.Length),
  data.frame(Type = Species), mean))
#        Type SLength
#1     setosa   5.006
#2 versicolor   5.936
#3  virginica   6.588

或者

aggregate(data.frame(SLength = iris$Sepal.Length),
  data.frame(Type = iris$Species), mean)
#        Type SLength
#1     setosa   5.006
#2 versicolor   5.936
#3  virginica   6.588

使用cbinddata.frame比较的优点list是并非所有列都需要指定一个(新的)名称。可以通过多个分组因子聚合多个列,如下所示:

aggregate(cbind("Miles/gallon" = mpg, Weight = wt, hp) ~ cbind(Cylinders =
  cyl) + cbind(Carburetors = carb) + gear, data = mtcars, mean)
#   Cylinders Carburetors gear Miles/gallon  Weight    hp
#1          4           1    3        21.50 2.46500  97.0
#2          6           1    3        19.75 3.33750 107.5
#...

如果您想使用多个功能:

aggregate(cbind(cases=ncases, ncontrols) ~ cbind(alc=alcgp) + tobgp,
  data = esoph, FUN = function(x) c("mean" = mean(x), "median" = median(x)))

#   alc    tobgp cases.mean cases.median ncontrols.mean ncontrols.median
#1    1 0-9g/day  1.5000000    1.0000000      43.500000        47.000000
#2    2 0-9g/day  5.6666667    4.0000000      29.833333        34.500000
#...

它将使用的聚合函数添加到 colname 中。

赫拉再次被他们的内部代码cbind取代。factors为避免这种情况,您可以使用:

with(esoph, aggregate(data.frame(cases=ncases, ncontrols),
 data.frame(alc=alcgp, tobgp),
 FUN = function(x) c("mean" = mean(x), "median" = median(x))))
#         alc    tobgp cases.mean cases.median ncontrols.mean ncontrols.median
#1  0-39g/day 0-9g/day  1.5000000    1.0000000      43.500000        47.000000
#2      40-79 0-9g/day  5.6666667    4.0000000      29.833333        34.500000
#...
于 2019-06-12T09:42:43.510 回答
-4
w <- data.frame(Funding<-"Fully Insured",Region="North East",claim_count=rnbinom(1000, 300.503572818, mu= 0.5739467))
x <- data.frame(Funding<-"Fully Insured",Region="South East",claim_count=rnbinom(1000, 1000, mu= 0.70000000))
y <- data.frame(Funding<-"Self Insured",Region="North East",claim_count=rnbinom(1000, 400, mu= 0.80000000))
z <- data.frame(Funding<-"Self Insured",Region="South East",claim_count=rnbinom(1000, 700, mu= 1.70000000))
names(w)<-c("Funding","Region","claim_count")
names(x)<-c("Funding","Region","claim_count")
names(y)<-c("Funding","Region","claim_count")
names(z)<-c("Funding","Region","claim_count")
my_df <- rbind(w,x,y,z)
my_df2<-with(my_df, aggregate(x=claim_count, by=list(Funding,Region), FUN=sum))
colnames(my_df2)<-colnames(my_df)
于 2015-08-18T23:07:10.953 回答