dplyr编程:过滤器的意外行为

时间:2017-09-11 19:03:51

标签: r dplyr non-standard-evaluation

我试图在编程方式中使用dplyr:使用带引号的变量进行过滤行为是不可理解的。

在多次尝试分析实际数据后,我创建了以下虚拟数据。

dt <- data.frame(
  sex = rep(c("F","M"), 50),
  height = runif(100, 1, 1000),
  weight = rep(c(2, 100), 50),
  value = runif(100, 1, 1000 ),
  stringsAsFactors =  FALSE
)



library(dplyr)


wizard_fun_1 <-  function(param1){
  par1 <- enquo(param1)

dt %>% select(height, !!par1)
}

wizard_fun_1("sex")

# as expected
#1    74.875344   F
#2   846.614856   M
#.....


wizard_fun_2 <-  function(param1){
  par1 <- enquo(param1)

  dt %>% select(height, !!par1)  %>%
    filter( (!!par1) == 'M')
}

wizard_fun_2('sex')

#[1] height sex  
# ... zero rows....

出了什么问题? 感谢先进的任何想法!

2 个答案:

答案 0 :(得分:1)

如果您使用enquo,则应该在没有引号的情况下调用您的函数。例如

wizard_fun_2(sex)

工作得很好。 select函数可以使用字符串或符号。这两个都可行

select(dt, sex) # more common
select(dt, "sex")

filter()

的情况并不相同
filter(sex=="M")
filter("sex"=="M")

在字符串和不带引号的符号/名称之间跳转时要小心。当您使用引用标记时,您根本就没有使用非标准评估。

答案 1 :(得分:1)

在您使用enquo的函数中,但是当您调用该函数时,您将列名称作为字符串而不是裸名称传递。你只需要在调用函数时使用裸列名称,它就像写的那样工作。


library(dplyr)
#> 
#> Attaching package: 'dplyr'
#> The following objects are masked from 'package:stats':
#> 
#>     filter, lag
#> The following objects are masked from 'package:base':
#> 
#>     intersect, setdiff, setequal, union

dt <- tibble(
  sex = rep(c("F","M"), 50),
  height = runif(100, 1, 1000),
  weight = rep(c(2, 100), 50),
  value = runif(100, 1, 1000 )
)


wizard_fun_2 <-  function(param1){
  par1 <- enquo(param1)

  dt %>% select(height, !!par1)  %>%
    filter( (!!par1) == "M")
}

wizard_fun_2(sex)

#> # A tibble: 50 x 2
#>      height   sex
#>       <dbl> <chr>
#>  1 871.7788     M
#>  2 467.9220     M
#>  3 272.6478     M
#>  4 445.1101     M
#>  5 682.2095     M
#>  6 831.8522     M
#>  7 727.9525     M
#>  8 203.7829     M
#>  9 742.3000     M
#> 10 322.0473     M
#> # ... with 40 more rows