与 dplyr 准报价混合输入

Mixed input in quasiquotation with dplyr

我已经将准报价提升到了最高水平。 我即将获得我的准引用大师徽章(请参阅下面的编辑)。还剩一位挑战者。

使用不同的输入通过 dplyr 创建 quosures。最终结果是:

the_quote <- quo( if_else(!!cond_expr, !!inter_quo, !!var_expr) )

而且我已经设法从自定义的 table 字符串构造了上面的表达式,如下所示:

var_expr <- as.name(rules_df$target_col)

cond_expr <- "make == '%s'" %>% sprintf(rules_df$context_col) %>% parse_expr()

inter_quo <- quo( 
    str_detect( !!var_expr, regex(!!rules_df$phrase_col) ))

其中 context_colphrase_coltarget_col 是 table 中的字符串列,我已经定义了参与规则。

示例:

rules_df <- data_frame(
    context_col = "BMW", 
    phrase_col  = "Serie X(\d)", 
    target_col  = "model")

cars_table <- data_frame(
    make = c("Mercedes", "BMW", "BMW"), 
    model = c("Viano", "Serie X5", "Z4"))

告诉我找到那些宝马的 Serie X5 ,我稍后会用 X5 替换它,但那是另一回事了。

在打印报价时,我注意到表达式运行良好,但中间 quosure 给出了错误。

> the_quote
<quosure>
  expr: ^if_else(marca == "BMW", 
            ^str_detect(model, regex("Serie X(\d)")), model)
  env:  000000002001DEE0

> mutate(cars_table, detect = !!the_quote)
Error: Evaluation error: `false` must be type logical, not character.

在quosure中我有一个额外的^,它将str_detect的结果转换成一个字符。

如何将这个中间quosure集成到外部quosure中?

谢谢。

编辑

查看解决方案后,最终发现此挑战中的问题不是引用,而是在 detect 列中正确使用 if_else。那就是将逻辑变为字符,或者只是让错误的子句相应地起作用。

因此,另一种解决方案是从头设置if_else(!!cond_expr, !!inter_quo, FALSE)

我们需要用as.character作为str_detectreturns一个逻辑class的包装,而if_elsefalse参数是返回 'character'。 if_else讲究class。因此,如果我们这样做

inter_quo <- quo( as.character(str_detect( !!var_expr, 
               regex(!!rules_df$phrase_col) )))

那么它应该可以工作

mutate(cars_table, detect = !!the_quote)
# A tibble: 3 x 3
#  make     model    detect
#  <chr>    <chr>    <chr> 
#1 Mercedes Viano    Viano 
#2 BMW      Serie X5 TRUE  
#3 BMW      Z4       FALSE