R按组过滤值填写新列

R fill in new column by filtered value by group

我想在我的 dat 中创建新列,按值填充 满足一个条件。所以,我想保留 value where where regime == "SA" 并将此值填充到新列 vals.sa 的整个组中。

这结合了 filtermutate,但我不确定它们的正确组合是什么? Filter 只是保持行满足条件,但如何将此值扩展到组中的所有行?

我的数据:

dat <- data.frame(id = c(1,1,2,2,2,2,3,3),
                  regime = c("SA", "B", "SA", "B", "C", "F", "SA", "D"),
                  value = c(3,5,1,2,5,6,7,8))

使用dplyr

处理数据
dat %>% 
  # group data by id
  group_by(id) %>%           
  # how to write this condition and get values instead or TRUE/FALSE?
  mutate(val.sa = regime == "SA") 

预期输出填充 val.sa 值对应 regime == "SA"

     id regime value val.sa
  <dbl> <fct>  <dbl>  <dbl>
1     1 SA         3      3
2     1 B          5      3
3     2 SA         1      1
4     2 B          2      1
5     2 C          5      1
6     2 F          6      1
7     3 SA         7      7
8     3 D          8      7

首先创建一个新列 val.sa,其中 SA 行中的值等于 value 列中的值。然后按 idfill 向下分组。像这样:

dat %>%
  mutate(val.sa = ifelse(regime == 'SA', value, NA)) %>%
  group_by(id) %>%
  fill(val.sa)
## A tibble: 8 x 4
## Groups:   id [3]
#     id regime value val.sa
#  <dbl> <chr>  <dbl>  <dbl>
#1     1 SA         3      3
#2     1 B          5      3
#3     2 SA         1      1
#4     2 B          2      1
#5     2 C          5      1
#6     2 F          6      1
#7     3 SA         7      7
#8     3 D          8      7

您可以使用:

library(dplyr)
dat %>%
  group_by(id) %>%
  mutate(value.sa = value[regime == 'SA'])
  #OR
  #mutate(value.sa = value[match('SA', regime)])


#     id regime value value.sa
#  <dbl> <chr>  <dbl>    <dbl>
#1     1 SA         3        3
#2     1 B          5        3
#3     2 SA         1        1
#4     2 B          2        1
#5     2 C          5        1
#6     2 F          6        1
#7     3 SA         7        7
#8     3 D          8        7

如果一个组中可能有多个 regime"SA",您可以使用 which.max/[=15 select 第一个值=].

dat %>%
  group_by(id) %>%
  mutate(value.sa = value[which.max(regime == 'SA')])

如果你总是在每组中只有一个 SA,这应该 运行 没有任何错误:

dat %>% 
  group_by(id) %>%             
  mutate(val.sa = value[regime == "SA"]) 
#> # A tibble: 8 x 4
#> # Groups:   id [3]
#>      id regime value val.sa
#>   <dbl> <fct>  <dbl>  <dbl>
#> 1     1 SA         3      3
#> 2     1 B          5      3
#> 3     2 SA         1      1
#> 4     2 B          2      1
#> 5     2 C          5      1
#> 6     2 F          6      1
#> 7     3 SA         7      7
#> 8     3 D          8      7

否则,您必须决定要保留哪个 SA-值。例如始终保持最大值:

dat <- data.frame(id = c(1,1,2,2,2,2,3,3),
                  regime = c("SA", "B", "SA", "SA", "C", "F", "SA", "D"),
                  value = c(3,5,1,2,5,6,7,8))
dat
#>   id regime value
#> 1  1     SA     3
#> 2  1      B     5
#> 3  2     SA     1
#> 4  2     SA     2
#> 5  2      C     5
#> 6  2      F     6
#> 7  3     SA     7
#> 8  3      D     8

dat %>% 
  group_by(id) %>%             
  mutate(val.sa = max(value[regime == "SA"]))
#> # A tibble: 8 x 4
#> # Groups:   id [3]
#>      id regime value val.sa
#>   <dbl> <fct>  <dbl>  <dbl>
#> 1     1 SA         3      3
#> 2     1 B          5      3
#> 3     2 SA         1      2
#> 4     2 SA         2      2
#> 5     2 C          5      2
#> 6     2 F          6      2
#> 7     3 SA         7      7
#> 8     3 D          8      7

我们可以使用case_when

library(dplyr)
library(tidyr)
 dat %>%
     mutate(val.sa = case_when(regime == 'SA' ~ value) %>%
     group_by(id) %>%
     fill(val.sa)