Фильтр на основе нескольких столбцов с аналогичной структурой именования - PullRequest
0 голосов
/ 30 апреля 2018

Я бы хотел filter мой tibble в нескольких столбцах с похожими именами. В частности, я бы хотел сравнить x с x_new, y с y_new и т. Д., Но без указания явного имени, но с использованием структуры в именах столбцов.

Я пытался использовать filter_at, но это не работает, так как я не знаю, как правильно вычислить формулу в последней строке.

my_df %>% 
  filter_at(vars(contains("_new")), any_vars(funs({
    x <- .
    x_name <- quo_name(quo(x))
    x_new_name <- str_replace(x_name, "_new", "")
    paste(x_name, "!=", x_new_name)
  })
  ))

Данные

my_df <- tibble(x = 1:5, 
                x_new = c(1:4, 1), 
                y = letters[1:5], 
                y_new = c(letters[1:3], "a", "e"))

# A tibble: 5 x 4
#       x x_new y     y_new
#   <int> <dbl> <chr> <chr>
# 1     1    1. a     a    
# 2     2    2. b     b    
# 3     3    3. c     c    
# 4     4    4. d     a    
# 5     5    1. e     e   

Ожидаемый результат

# A tibble: 2 x 4
#       x x_new y     y_new
#   <int> <dbl> <chr> <chr>
# 1     4    4. d     a    
# 2     5    1. e     e 

1 Ответ

0 голосов
/ 30 апреля 2018

Мы могли бы сделать это с map. Создайте вектор из unique имен, удалив суффиксную часть имен столбцов ('nm1'). Прокрутите «nm1», выберите столбцы, которые matches имя столбца, reduce для одного логического вектора, проверив, не равны ли строки, затем reduce list логических векторов для одного логический вектор и extract строки на основе этого

library(tidyverse)
nm1 <- unique(sub("_.*", "", names(my_df)))
map(nm1, ~ my_df %>% 
                select_at(vars(matches(.x))) %>% 
                reduce(`!=`)) %>% 
       reduce(`|`) %>% 
       magrittr::extract(my_df, ., )
#    x x_new y     y_new
#  <int> <dbl> <chr> <chr>
#1     4     4 d     a    
#2     5     1 e     e    

Другой вариант - создать выражение и затем оценить

library(rlang)
nm1 <- names(my_df) %>% 
          split(sub("_.*", "", .)) %>%
          map(~ paste(.x, collapse=" != ") %>%
                   paste0("(", ., ")")) %>%
          reduce(paste, sep = "|")
my_df %>%
   filter(!! parse_expr(nm1))
# A tibble: 2 x 4
#     x x_new y     y_new
# <int> <dbl> <chr> <chr>
#1    4     4 d     a    
#2    5     1 e     e    
...