在group_by中选择值并根据R中的另一列值进行汇总

时间:2019-01-02 17:25:17

标签: r dplyr tidyverse

在以下示例中,如何根据另一列(mpg)中的条件为每个组(cyl)选择一个值(从carb == 1)。请注意,我还想总结另一个变量(每组平均qsec)。我最好的猜测是出现以下错误:

library(dplyr)
mtcars %>% 
    distinct(cyl, carb, .keep_all = TRUE) %>% 
    group_by(cyl) %>% 
    summarize(
        mpg = mpg[.$carb == 1],
        qsec = mean(qsec)
    )

1 个答案:

答案 0 :(得分:1)

如果有多个行的'carb'为1,并且summarise每组仅返回一行或不返回任何组,则最好将输出包装在list中。如果我们使用$,它将破坏分组

library(tidyverse)
out <- mtcars %>% 
        distinct(cyl, carb, .keep_all = TRUE) %>% 
        group_by(cyl) %>% 
        summarize(
          mpg = list(mpg[carb == 1]),
          qsec = mean(qsec)
        ) 

out
# A tibble: 3 x 3
#    cyl mpg        qsec
#  <dbl> <list>    <dbl>
#1     4 <dbl [1]>  19.3
#2     6 <dbl [1]>  17.1
#3     8 <dbl [0]>  16.2

通过查看输出,对于'cyl'8,没有等于'1'的'carb',结果为numeric(0)

通过用replace_na包装,可以将长度为0的元素更改为NA,然后执行unnest。否则,如评论中的@Dave Gruenewald所述,该行可以在unnest ing

时自动删除。
out %>% 
  mutate(mpg = replace_na(mpg)) %>% 
  unnest
# A tibble: 3 x 3
#    cyl  qsec   mpg
#  <dbl> <dbl> <dbl>
#1     4  19.3  22.8
#2     6  17.1  21.4
#3     8  16.2  NA  

另一种选择,如果我们已经知道'carb'中最多有1个元素等于1,则在if/else中使用summarise条件

mtcars %>%
    distinct(cyl, carb, .keep_all = TRUE) %>% 
    group_by(cyl) %>%
    summarise(
       mpg = if(any(carb == 1)) mpg[carb==1] else NA_real_,
       qsec = mean(qsec)
 )
# A tibble: 3 x 3
#     cyl   mpg  qsec
#   <dbl> <dbl> <dbl>
#1     4  22.8  19.3
#2     6  21.4  17.1
#3     8  NA    16.2

但是,最好假设每个“ cyl”可以有多个“ carb”值(分别为1),然后将其包装在list之后,再unnest

mtcars %>%
    distinct(cyl, carb, .keep_all = TRUE) %>% 
    group_by(cyl) %>%
    summarise(
       mpg = list(if(any(carb == 1)) mpg[carb==1] else NA_real_),
       qsec = mean(qsec)) %>%
    unnest