aggregate()将多个输出列放在矩阵中

时间:2015-01-14 13:21:15

标签: r aggregate

我要为某个变量计算多个分位数:

> res1 <- aggregate(airquality$Wind, list(airquality$Month), function (x) quantile(x, c(0.9, 0.95, 0.975)))
> head(res1)
  Group.1   x.90%   x.95% x.97.5%
1       5 16.6000 17.5000 18.8250
2       6 14.9000 15.5600 17.3650
3       7 14.3000 14.6000 14.9000
4       8 12.6000 14.0500 14.6000
5       9 14.9600 15.5000 15.8025

结果看起来效果很好,但聚合实际上以一种非常奇怪的形式返回它,其中最后3列不是data.frame的列,而是单个矩阵!

> names(res1)
[1] "Group.1" "x"      
> dim(res1)
[1] 5 2
> class(res1[,2])
[1] "matrix"

这会在进一步处理中引起很多问题。

几个问题:

  1. 为什么aggregate()表现得如此奇怪?
  2. 有什么办法吗? 说服它取得我期望的结果?
  3. 或者我也许正在使用 为此目的错误的功能?有没有其他优先方式 得到想要的结果?
  4. 当然我可以对aggregate()的输出进行一些转换,但我想寻找一些更简单直接的解决方案。

1 个答案:

答案 0 :(得分:11)

Q1:为什么这种行为如此奇怪?

这实际上是?aggregate的记录行为(虽然它可能仍然是意料之外的)。要查看的相关论点是simplify

如果simplify设置为FALSE,则aggregate会产生list,而不是像这样。

res2 <- aggregate(airquality$Wind, list(airquality$Month), function (x) 
  quantile(x, c(0.9, 0.95, 0.975)), simplify = FALSE)
str(res2)
# 'data.frame':  5 obs. of  2 variables:
#  $ Group.1: int  5 6 7 8 9
#  $ x      :List of 5
#   ..$ 1  : Named num  16.6 17.5 18.8
#   .. ..- attr(*, "names")= chr  "90%" "95%" "97.5%"
#   ..$ 32 : Named num  14.9 15.6 17.4
#   .. ..- attr(*, "names")= chr  "90%" "95%" "97.5%"
#   ..$ 62 : Named num  14.3 14.6 14.9
#   .. ..- attr(*, "names")= chr  "90%" "95%" "97.5%"
#   ..$ 93 : Named num  12.6 14.1 14.6
#   .. ..- attr(*, "names")= chr  "90%" "95%" "97.5%"
#   ..$ 124: Named num  15 15.5 15.8
#   .. ..- attr(*, "names")= chr  "90%" "95%" "97.5%"

现在,作为列的matrixlist似乎都是奇怪的行为,但我认为它更像是“设计状态”而不是“错误”或“缺陷”。

例如,请考虑以下内容:我们希望聚合“airquality”数据集中的“Wind”和“Temp”列,并且我们知道每个聚合都会产生多个列(就像我们期望的那样{ {1}})。

quantile

在某些方面,将这些值保留为res3 <- aggregate(cbind(Wind, Temp) ~ Month, airquality, function (x) quantile(x, c(0.9, 0.95, 0.975))) res3 # Month Wind.90% Wind.95% Wind.97.5% Temp.90% Temp.95% Temp.97.5% # 1 5 16.6000 17.5000 18.8250 74.000 77.500 79.500 # 2 6 14.9000 15.5600 17.3650 87.300 91.100 92.275 # 3 7 14.3000 14.6000 14.9000 89.000 91.500 92.000 # 4 8 12.6000 14.0500 14.6000 94.000 95.000 96.250 # 5 9 14.9600 15.5000 15.8025 91.100 92.550 93.000 - 列可能有意义 - 数据汇总数据可通过其原始列名轻松访问:

matrix

Q2:如何将结果作为res3$Temp # 90% 95% 97.5% # [1,] 74.0 77.50 79.500 # [2,] 87.3 91.10 92.275 # [3,] 89.0 91.50 92.000 # [4,] 94.0 95.00 96.250 # [5,] 91.1 92.55 93.000 中的单独列?

但是data.frame作为列在许多情况下作为列list处理起来同样尴尬。如果您想将matrix“展平”到列中,请使用matrix

do.call(data.frame, ...)

问题3:还有其他选择吗?

和大多数事情一样,R当然是。我首选的选择是使用“data.table”包,您可以使用它:

do.call(data.frame, res1)
#   Group.1 x.90. x.95. x.97.5.
# 1       5 16.60 17.50 18.8250
# 2       6 14.90 15.56 17.3650
# 3       7 14.30 14.60 14.9000
# 4       8 12.60 14.05 14.6000
# 5       9 14.96 15.50 15.8025
str(.Last.value)
# 'data.frame':  5 obs. of  4 variables:
#  $ Group.1: int  5 6 7 8 9
#  $ x.90.  : num  16.6 14.9 14.3 12.6 15
#  $ x.95.  : num  17.5 15.6 14.6 14.1 15.5
#  $ x.97.5.: num  18.8 17.4 14.9 14.6 15.8a