使用聚合来方便计算

Use aggregate to facilitate calculations

所以最近我一直在学习聚合的功能,我发现它对我处理的大型数据集非常有用。通常我手动操作 excel 中的数据,虽然有效,但非常耗时。

所以我想知道是否可以完成以下操作。我有一个结构类似的数据集(但更大):

Fruit    Crate   Mass
Apple    A       4
Banana   A       3.4
Orange   B       2
Apple    C       2.1
Apple    C       4.5
Banana   C       5
Orange   D       1
Apple    D       1.3
Orange   D       2.4
Orange   D       3.2
Orange   E       2
Banana   E       1.1
Banana   E       0.7
Apple    E       2

现在我知道我得到了每个板条箱的质量:

TotalCrate<-aggregate(data$Mass,list(crate=data$Crate), sum)

然后我得到每个板条箱每个水果的质量:

FruitperCrate<-aggregate(data$Mass, list(fruit=data$Fruit, crate=data$Crate), sum)

现在有没有一种方法可以获得每个板条箱的水果质量百分比,所以基本上,有没有一种方法可以将水果质量除以每个板条箱的总质量?如果是这样,我该如何做以供将来参考。

感谢任何帮助。

谢谢

这里有一个解决方案,使用 data.table,当然还有其他方法:

library( data.table )
setDT( data )
data[ , mass := sum( mass ), by = .( crate, fruit ) ]
data <- unique( data )
data[ , total.mass.crate := sum( mass ), by = crate ]
data[ , percentage.mass.crate := ( mass / total.mass.crate ) * 100 ]

所以我们首先汇总每个板条箱中每个水果的质量(因为我注意到有些水果在一个板条箱中不止一次列出)以获得板条箱中该水果的总质量。然后我们添加一列来显示每个板条箱的总质量,显示每一行的值。然后,通过将每个水果的质量除以该箱子的总质量,我们得到箱子中每个水果的质量百分比。

1)先用FruitCrate聚合,然后用aveprop.table得到比例箱子里的每个水果:

ag <- aggregate(Mass ~ Fruit + Crate, data, sum)
tr <- transform(ag, percent = 100 * ave(Mass, Crate, FUN = prop.table))

给予:

> tr
    Fruit Crate Mass   percent
1   Apple     A  4.0  54.05405
2  Banana     A  3.4  45.94595
3  Orange     B  2.0 100.00000
4   Apple     C  6.6  56.89655
5  Banana     C  5.0  43.10345
6   Apple     D  1.3  16.45570
7  Orange     D  6.6  83.54430
8   Apple     E  2.0  34.48276
9  Banana     E  1.8  31.03448
10 Orange     E  2.0  34.48276

或图形化:

library(ggplot2)
ggplot(tr, aes(Crate, percent, fill = Fruit)) + 
   geom_bar(stat = "identity") + 
   scale_fill_manual(values = c("red", "yellow", "orange"))

1a) 这也可以用这样的 magrittr 管道表示:

library(magrittr)
data %>%
     do(aggregate(Mass ~ Fruit + Crate, ., sum)) %>%
     transform(percent = 100 * ave(Mass, Crate, FUN = prop.table))

2) 这是使用遵循类似逻辑的 dplyr 的替代方法:

library(dplyr)
data %>% 
   group_by(Crate, Fruit) %>%
   summarize(Mass = sum(Mass)) %>%
   ungroup() %>%
   group_by(Crate) %>%
   mutate(percent = 100 * prop.table(Mass)) %>%
   ungroup()

给予:

# A tibble: 10 x 4
    Crate  Fruit  Mass   percent
   <fctr> <fctr> <dbl>     <dbl>
1       A  Apple   4.0  54.05405
2       A Banana   3.4  45.94595
3       B Orange   2.0 100.00000
4       C  Apple   6.6  56.89655
5       C Banana   5.0  43.10345
6       D  Apple   1.3  16.45570
7       D Orange   6.6  83.54430
8       E  Apple   2.0  34.48276
9       E Banana   1.8  31.03448
10      E Orange   2.0  34.48276

3) 二维布局可以使用 xtabs:

xt <- 100 * prop.table(xtabs(Mass ~ Crate + Fruit, data), 1)

给予:

> xt
     Fruit
Crate     Apple    Banana    Orange
    A  54.05405  45.94595   0.00000
    B   0.00000   0.00000 100.00000
    C  56.89655  43.10345   0.00000
    D  16.45570   0.00000  83.54430
    E  34.48276  31.03448  34.48276

可以很容易地用如下图表显示:

plot(xt, col = c("red", "yellow", "orange"), 
     main = "Proportion of Mass of Fruit per Crates")

给予:

二维布局可以改成长格式 ftable:

ftable(xt, row.vars = 1:2)

给予:

Crate Fruit            
A     Apple    54.05405
      Banana   45.94595
      Orange    0.00000
B     Apple     0.00000
      Banana    0.00000
      Orange  100.00000
C     Apple    56.89655
      Banana   43.10345
      Orange    0.00000
D     Apple    16.45570
      Banana    0.00000
      Orange   83.54430
E     Apple    34.48276
      Banana   31.03448
      Orange   34.48276

注1:题目中的两行代码可以用公式写成这样:

aggregate(Mass ~ Crate, data, sum)

aggregate(Mass ~ Fruit + Crate, data, sum)

注释 2: 以可重现形式使用的输入是:

Lines <- "Fruit    Crate   Mass
Apple    A       4
Banana   A       3.4
Orange   B       2
Apple    C       2.1
Apple    C       4.5
Banana   C       5
Orange   D       1
Apple    D       1.3
Orange   D       2.4
Orange   D       3.2
Orange   E       2
Banana   E       1.1
Banana   E       0.7
Apple    E       2"
data <- read.table(text = Lines, header = TRUE)