使用dplyr进行过滤,并将列名和条件作为字符串

时间:2019-10-07 17:45:29

标签: r dplyr purrr

我尝试编写一个简单的函数来过滤data.frame。列名和过滤条件都存储为字符串:

vars <- c("manufacturer", "engine")
cond <- c("EMBRAER", "Turbo-fan")

输出应与通过以下方式获得的输出相同:

library(dplyr)
library(nycflights13)

nycflights13::planes %>%
  filter(
    .data[[vars[[1]]]] == cond[[1]],
    .data[[vars[[2]]]] == cond[[2]]
  )

使用dplyr + purrr进行此操作的方式是什么?实际上,两个字符串的长度都更长。

2 个答案:

答案 0 :(得分:3)

对此进行考虑的另一种方法是,您具有要用于过滤主数据的条件数据集。创建一个包含条件及其相应变量名的小型数据框,然后将其重塑为一个数据框,其中这些变量名是列名。然后使用semi_join将只有变量和条件组合匹配的数据行保留在条件数据框中。

vars <- c("manufacturer", "engine")
cond <- c("EMBRAER", "Turbo-fan")

library(dplyr)
library(nycflights13)

cond_df <- data.frame(vars, cond) %>%
  tidyr::spread(key = vars, value = cond)

nycflights13::planes %>%
  semi_join(cond_df, by = vars)
#> # A tibble: 298 x 9
#>    tailnum  year type        manufacturer model  engines seats speed engine
#>    <chr>   <int> <chr>       <chr>        <chr>    <int> <int> <int> <chr> 
#>  1 N10156   2004 Fixed wing… EMBRAER      EMB-1…       2    55    NA Turbo…
#>  2 N10575   2002 Fixed wing… EMBRAER      EMB-1…       2    55    NA Turbo…
#>  3 N11106   2002 Fixed wing… EMBRAER      EMB-1…       2    55    NA Turbo…
#>  4 N11107   2002 Fixed wing… EMBRAER      EMB-1…       2    55    NA Turbo…
#>  5 N11109   2002 Fixed wing… EMBRAER      EMB-1…       2    55    NA Turbo…
#>  6 N11113   2002 Fixed wing… EMBRAER      EMB-1…       2    55    NA Turbo…
#>  7 N11119   2002 Fixed wing… EMBRAER      EMB-1…       2    55    NA Turbo…
#>  8 N11121   2003 Fixed wing… EMBRAER      EMB-1…       2    55    NA Turbo…
#>  9 N11127   2003 Fixed wing… EMBRAER      EMB-1…       2    55    NA Turbo…
#> 10 N11137   2003 Fixed wing… EMBRAER      EMB-1…       2    55    NA Turbo…
#> # … with 288 more rows

答案 1 :(得分:2)

1)sym -我们可以转换为sym大括号和eval uate(!!)。 [[主要用于提取list元素。正如OP显示vector的{​​{1}}一样,'vars'和'cond'足以提取每个元素

[

2)parse_expr-:一种选择是使用nycflights13::planes %>% filter( !!rlang::sym(vars[1]) == cond[1], !!rlang::sym(vars[2]) == cond[2] ) 中的pastestr_c创建一个表达式,然后解析该表达式

stringr

3)map2 / reduce-如果我们有多于一列,则可以使用expr1 <- str_c(vars, str_c('"', cond, '"'), sep="==", collapse=" & ") nycflights13::planes %>% filter(!! rlang::parse_expr(expr1)) # A tibble: 298 x 9 # tailnum year type manufacturer model engines seats speed engine # <chr> <int> <chr> <chr> <chr> <int> <int> <int> <chr> # 1 N10156 2004 Fixed wing multi engine EMBRAER EMB-145XR 2 55 NA Turbo-fan # 2 N10575 2002 Fixed wing multi engine EMBRAER EMB-145LR 2 55 NA Turbo-fan # 3 N11106 2002 Fixed wing multi engine EMBRAER EMB-145XR 2 55 NA Turbo-fan # 4 N11107 2002 Fixed wing multi engine EMBRAER EMB-145XR 2 55 NA Turbo-fan # 5 N11109 2002 Fixed wing multi engine EMBRAER EMB-145XR 2 55 NA Turbo-fan # 6 N11113 2002 Fixed wing multi engine EMBRAER EMB-145XR 2 55 NA Turbo-fan # 7 N11119 2002 Fixed wing multi engine EMBRAER EMB-145XR 2 55 NA Turbo-fan # 8 N11121 2003 Fixed wing multi engine EMBRAER EMB-145XR 2 55 NA Turbo-fan # 9 N11127 2003 Fixed wing multi engine EMBRAER EMB-145XR 2 55 NA Turbo-fan #10 N11137 2003 Fixed wing multi engine EMBRAER EMB-145XR 2 55 NA Turbo-fan # … with 288 more rows ,但是这里的“条件”是不同的。因此,一种选择是filter_at

map2