【问题标题】:dplyr programming: unexpected behavior of filterdplyr 编程:过滤器的意外行为
【发布时间】:2017-09-11 19:03:51
【问题描述】:

我正在尝试以编程方式使用 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....

怎么了? 提前感谢您的任何想法!

【问题讨论】:

  • 请参阅here,了解如何使用字符串作为输入。

标签: r dplyr non-standard-evaluation


【解决方案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

【讨论】:

    【解决方案2】:

    如果你使用enquo,你应该在调用你的函数时不带引号。例如

    wizard_fun_2(sex)
    

    可以正常工作。 select 函数可以接受字符串或符号。那就是这两个都行

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

    filter() 不一样

    filter(sex=="M")
    filter("sex"=="M")
    

    所以在字符串和未加引号的符号/名称之间跳转时要小心。当您使用报价时,您根本没有使用非标准评估。

    【讨论】:

    • @aosmith 有人可以告诉我如何使用指定变量和filter 的函数的字符参数来实际执行此操作吗?我的quosym 等咒语都不起作用。
    • @joran: f &lt;- function(param1){ par1&lt;- rlang::sym(param1); dt %&gt;% select(height, !!(par1)) %&gt;% filter( (!!par1) == 'M') }; f("sex") 应该可以解决问题。
    • 啊,哎呀,你似乎必须在(!!par1) 中有括号。这似乎……很棘手。
    • @joran。是啊。 == 的优先级高于 !。由于 bang 运算符从来没有真正打算以这种方式使用,所以会发生这样的事情
    • @MrFlick,感谢您的 sn-p。这正是我需要的)))耶)))
    猜你喜欢
    • 2019-09-21
    • 1970-01-01
    • 2019-09-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多