在R语言中,根据另一列的值选择分组并进行总结。

5
在以下示例中,我如何选择每个组(cyl)中的值(从mpg),取决于另一列中的条件(carb == 1)。请注意,我还想对另一个变量进行汇总(平均每个组的qsec)。我的最佳猜测如下面代码,但会出现错误:
library(dplyr)
mtcars %>% 
    distinct(cyl, carb, .keep_all = TRUE) %>% 
    group_by(cyl) %>% 
    summarize(
        mpg = mpg[.$carb == 1],
        qsec = mean(qsec)
    )
1个回答

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

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

通过使用replace_na包装,长度为0的元素可以更改为NA,然后执行unnest。 否则,如@Dave Gruenewald在评论中提到的那样,在unnest时该行可能会被自动删除。

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,那么在summarise中可以使用if/else条件的另一种选项。

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”都有多个值为1的“carb”值,并将其包装在一个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

1
这里有关于使用unnest删除空行的更多信息 - https://github.com/tidyverse/tidyr/issues/358 - Dave Gruenewald

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接