【问题标题】:Name columns within aggregate in R在 R 中的聚合中命名列
【发布时间】:2013-02-24 21:29:13
【问题描述】:

我知道我可以在聚合数据后*重新*命名列:

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"))

【问题讨论】:

    标签: r rename aggregate


    【解决方案1】:

    您可以使用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
    

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

    这里是a Gist,应用了这个概念,创建了一个名为“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)"
    

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

    【讨论】:

    • 谢谢。这是否意味着绝对不可能在 aggregate() 括号内设置列名?另外,我编辑了我的问题,也许你对我问题的后半部分有进一步的想法。
    • 我喜欢另一种选择 :-)
    • 稍后我会调查您的问题。同时,查看this wrapper 周围的aggregate,它附加了应用于聚合列名称的函数。我没有在我的答案中发布它,因为它确实在一定程度上限制了 aggregate 的功能,并且只是为我正在从事的项目编写的。
    • 也可以使用不带list()的名称。 blubb &lt;- aggregate(One = dat$one, Two = dat$two, data=dat...)
    • @Matt,(1)这似乎对我不起作用,(2)这对多个分组变量如何起作用,(3)如果你需要dat$指定data=dat(这是aggregateformula 方法的参数,而不是您在此处提出的方法)。如果我遗漏了什么,请告诉我。谢谢!
    【解决方案2】:

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

    blubb &lt;- aggregate(dat,list(One=dat$One,Two=dat$Two),sum)

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

    【讨论】:

    • 你如何更改函数sum产生的列的名称?现在只是x
    • @andrewj 我相信你可以把它放在函数的“列表”部分,例如...list(One = dat$One, Two = dat$Two, MyResults = dat$x) ...
    【解决方案3】:
    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)
    

    【讨论】:

      【解决方案4】:

      如果您更喜欢将聚合编写为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
      

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

      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 中。

      Hera 再次将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
      #...
      

      【讨论】:

        猜你喜欢
        • 2017-03-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-12-02
        • 2016-11-29
        • 2021-12-24
        • 2020-04-02
        相关资源
        最近更新 更多