1

我有一个看起来像这样的数据集,有很多类,每个类都有很多(5-10)个子类,每个子类都有一个与之关联的值:

> data.frame(class=rep(letters[1:4], each=4), subclass=c(1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8), value=1:16)
   class subclass value
1      a        1     1
2      a        1     2
3      a        2     3
4      a        2     4
5      b        3     5
6      b        3     6
7      b        4     7
8      b        4     8
9      c        5     9
10     c        5    10
11     c        6    11
12     c        6    12
13     d        7    13
14     d        7    14
15     d        8    15
16     d        8    16

我想首先对每个类/子类的值求和,然后在所有子类中取每个类的中值。

即,中间步骤将对每个类的每个子类的值求和,看起来像这样(请注意,我不需要保留此中间步骤的数据):

> data.frame(class=rep(letters[1:4], each=2), subclass=1:8, sum=c(3,7,11,15,19,23,27,31))
  class subclass   sum
1     a        1     3
2     a        2     7
3     b        3    11
4     b        4    15
5     c        5    19
6     c        6    23
7     d        7    27
8     d        8    31

第二步将获取所有子类中每个类的中位数,如下所示:

> data.frame(class=letters[1:4], median=c(median(c(3,7)), median(c(11,15)), median(c(19,23)), median(c(27,31))))
  class median
1     a      5
2     b     13
3     c     21
4     d     29

这是我需要保留的唯一数据。请注意,$class 和 $subclass 都将是因子变量,并且 value 将始终是一个非缺失的正整数。每个类都有不同数量的子类。

我确信我可以用一些讨厌的 for 循环来做到这一点,但我希望有一种更好的方法,它可以矢量化并且更容易维护。

4

3 回答 3

3

这是另一个使用示例aggregate

temp <- aggregate(df$value,list(class=df$class,subclass=df$subclass),sum)

aggregate(temp$x,list(class=temp$class),median)

输出:

      class  x
  1     a    5
  2     b   13
  3     c   21
  4     d   29

或者,如果您喜欢单线解决方案,您可以执行以下操作:

aggregate(value ~ class, median, data=aggregate(value ~ ., sum, data=df))
于 2013-03-02T19:35:10.473 回答
2

您可以尝试第一步:

df_sums <- aggregate(value ~ class + subclass, sum, data=df)

然后:

aggregate(value ~ class, median, data=df_sums)
于 2013-03-02T19:22:10.130 回答
2

这是另外两个选择。

第一次avewithin语句中使用,我们data.frame在添加聚合数据后逐渐减少源。由于这将导致许多重复的行,我们可以安全地使用unique作为最后一步来获得您想要的输出。

unique(within(mydf, {
  Sum <- ave(value, class, subclass, FUN = sum)
  rm(subclass, value)
  Median <- ave(Sum, class, FUN = median)
  rm(Sum)
}))
#    class Median
# 1      a      5
# 5      b     13
# 9      c     21
# 13     d     29

第二种选择是使用“data.table”包并“复合”您的陈述,如下所示。如果用户未指定V1名称,将自动创建的名称。data.table

library(data.table)
DT <- data.table(mydf)
DT[, sum(value), by = c("class", "subclass")][, median(V1), by = "class"]
#    class V1
# 1:     a  5
# 2:     b 13
# 3:     c 21
# 4:     d 29
于 2013-03-03T15:48:00.203 回答