Отфильтруйте tibble для определенной переменной, но сохраняйте не совпадающие строки и заполняйте NA/NULL

#r #tidyverse #tidyr

Вопрос:

У меня есть этот tibble, и я хочу отфильтровать его по всем идентификаторам элемента, но дополнительно сохранить все строки и заполнить эти строки NA или 0.

 library(tibble)
tibble::tibble(item=c("a", "a", "a", "b", "b", "b", "c", "c", "c"), 
               id=c("10","11","12","10","15","16","8","9","12"),
               val=c(25,27,31,24,38,39,12,14,39))

# A tibble: 9 x 3
  item  id      val
  <chr> <chr> <dbl>
1 a     10       25
2 a     11       27
3 a     12       31
4 b     10       24
5 b     15       38
6 b     16       39
7 c     8        12
8 c     9        14
9 c     12       39
 

Например, я хочу отфильтровать все идентификаторы элемента a (т. Е. 10, 11, 12 ), и мой желаемый тиббл будет выглядеть так, где я сохраняю все не совпадающие строки и заполняю <chr> NA <dbl> их и с 0 .

 # A tibble: 9 x 3
  item  id      val
  <chr> <chr> <dbl>
1 a     10       25
2 a     11       27
3 a     12       31
4 b     10       24
5 b     NA        0
6 b     NA        0
7 c     NA        0
8 c     NA        0
9 c     12       39
 

Ответ №1:

Вы можете использовать replace или ifelse

 library(dplyr)

keep <- c(10, 11, 12)

df %>%
  mutate(val = replace(val, !id %in% keep, 0), 
         id = replace(id, !id %in% keep, NA))

#  item  id      val
#  <chr> <chr> <dbl>
#1 a     10       25
#2 a     11       27
#3 a     12       31
#4 b     10       24
#5 b     NA        0
#6 b     NA        0
#7 c     NA        0
#8 c     NA        0
#9 c     12       39
 

Если у вас много столбцов, вы можете использовать across

 df %>%
  mutate(across(c(where(is.character), -item), ~replace(., !id %in% keep, NA)), 
         across(where(is.numeric), ~replace(., !id %in% keep, 0)))