基于多个具有相似命名结构的列进行过滤

Filter based on several columns with similar naming structure

我想 filter 我的 tibble 在几个名称相似的专栏上。具体来说,我想将 xx_newyy_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 

我们可以用 map 做到这一点。通过删除列名 ('nm1') 的后缀部分,创建一个包含 unique 个名称的向量。遍历 'nm1'、select 列 matches 列名称,reduce 通过检查行是否不相等将其循环到单个逻辑向量,然后 reducelist 个逻辑向量转换为单个逻辑向量,并 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