【问题标题】:Filter based on several columns with similar naming structure基于具有相似命名结构的多个列进行过滤
【发布时间】:2018-04-30 11:55:46
【问题描述】:

我想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 

【问题讨论】:

  • 你有最后一行paste(x_name, "!=", x_new_name) 没有被评估
  • 是的,但我该如何评估呢?我试过eval!!,但它不起作用。问题是,我猜,评估的环境还不清楚......
  • 另外,您正在尝试对相似的列进行分组并进行比较。可能你需要map

标签: r dplyr nse


【解决方案1】:

我们可以使用map 来做到这一点。通过删除列名 ('nm1') 的后缀部分来创建 unique 名称的向量。遍历'nm1',通过检查行是否不相等来选择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    

【讨论】:

  • 它有效,但我想知道是否有 filter_at 或类似的解决方案而不“退出”管道。
  • @kath 如果您检查quo_name(quo(x)) 的输出,它会返回“x”而不是列名
  • 确实是这样,但是我改了x_name &lt;- quo_name(quo(.)),所以返回了正确的名字,但是还是不能用合适的方式写filter-call...
猜你喜欢
  • 2021-06-28
  • 1970-01-01
  • 2021-07-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多