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

Dav*_*ger 5 r dplyr tidyverse

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

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

akr*_*run 2

如果有多个行的 '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
Run Code Online (Sandbox Code Playgroud)

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

通过用 包裹起来replace_na,长度为 0 的元素可以更改为NA,然后执行unnest。否则,正如 @Dave Gruenewald 在评论中提到的,该行可以在unnesting时自动删除

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  
Run Code Online (Sandbox Code Playgroud)

另一种选择,如果我们已经知道“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
Run Code Online (Sandbox Code Playgroud)

然而,最好假设可能有多个“carb”值,每个“cyl”为 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
Run Code Online (Sandbox Code Playgroud)