使用dplyr创建多行摘要,例如分组表()

时间:2018-04-18 16:02:54

标签: r dplyr aggregate

我的数据集包括多种植物(基因型)的植物观察结果 环境。此示例数据包含每个观察的一行 我有。它列出了植物基因型和观察的环境 是的。

nObs <- 500
data <- tibble(Gt  = sample(sprintf("%02d",1:20),nObs,T),
               Env = sample(LETTERS\[1:8\],nObs,T)
               # The measured plant trait would also go here but is irrelevant for now.
               )

我想要的是一张表格,它显示了我在多少环境中的每种基因型 它重复了多少次。例如,如果我的基因型01有两次重复 在五个环境中,但在另外两个环境中只有一个,即输出 我期待的是:

Genotype  nRepl  nEnv
---------------------
 A        2      5
 A        1      2

我找到了使用do的可能性,但由于do期望它很慢 为每个包含摘要信息的数据子组创建的数据帧。这创造了很多 开销,正如您在分析时所看到的那样:

profvis::profvis(for(1:10) idea1())  #idea1 is defined below

profiler output

是否有其他方法,可能没有使用do(.),这会给出这个结果?

到目前为止,我的想法如下所示:

这将返回每个基因型中每个基因型的观察次数 环境(=复制):

data %>% count(Gt, Env) 

## # A tibble: 158 x 3
##    Gt    Env       n
##    <chr> <chr> <int>
##  1 01    A         2
##  2 01    B         1
##  3 01    C         2
##  4 01    D         2
##  5 01    E         6
##  6 01    F         4
##  7 01    G         5
##  8 01    H         3
##  9 02    A         1
## 10 02    B         2
## # ... with 148 more rows

到目前为止,这是我能提出的三种方法。全部使用do

idea1 <- function(){
  data %>% count(Gt, Env) %>% group_by(Gt) %>%
    do({
      t <- table(.$n)
      tibble(nRpl = names(t), nEnv = as.integer(t))
    })
}

idea2 <- function(){
  data %>% count(Gt, Env) %>% group_by(Gt) %>%
    do({
      t <- table(.$n)
      data.frame(nRpl = names(t), nEnv = as.integer(t), stringsAsFactors = FALSE)
    })
}

idea3 <- function(){
  data %>% count(Gt, Env) %>% group_by(Gt) %>%
    do({
      t <- table(.$n)
      data.frame(nRpl = names(t), nEnv = as.integer(t), stringsAsFactors = FALSE,
                 check.names = FALSE, check.rows = FALSE)
    })
}

这是我想要的输出:

idea1()

## # A tibble: 93 x 3
## # Groups:   Gt [20]
##    Gt    nRpl   nEnv
##    <chr> <chr> <int>
##  1 01    1         1
##  2 01    2         3
##  3 01    3         1
##  4 01    4         1
##  5 01    5         1
##  6 01    6         1
##  7 02    1         1
##  8 02    2         4
##  9 02    4         1
## 10 02    6         1
## # ... with 83 more rows

速度比较:

library(microbenchmark)
microbenchmark({idea1()},{idea3()},{idea4()}, times = 20)

## Unit: milliseconds
##             expr       min        lq     mean   median       uq      max
##  {     idea1() } 299.21640 373.87930 435.2567 427.8721 460.7488 693.9279
##  {     idea3() }  80.03300 100.25709 144.8413 124.8140 182.9211 300.3150
##  {     idea4() }  83.04371  98.18572 122.6464 108.1945 141.0208 216.3999
##  neval
##     20
##     20
##     20

1 个答案:

答案 0 :(得分:1)

您可以使用count两次,第二次计算第一次计算的复制次数:

library(dplyr)
set.seed(47)    # for sampling reproducibility

data <- tibble(Gt  = sample(sprintf("%02d", 1:20), 500, replace = TRUE),
               Env = sample(LETTERS[1:8], 500, replace = TRUE))

data %>% 
    count(Gt, Env) %>% 
    count(Gt, n) %>% 
    rename(nRpl = n, nEnv = nn)    # make better names
#> # A tibble: 85 x 3
#>    Gt     nRpl  nEnv
#>    <chr> <int> <int>
#>  1 01        2     1
#>  2 01        3     4
#>  3 01        4     3
#>  4 02        2     1
#>  5 02        3     1
#>  6 02        4     3
#>  7 02        6     1
#>  8 03        1     3
#>  9 03        2     1
#> 10 03        3     1
#> # ... with 75 more rows