【问题标题】:Mixed input in quasiquotation with dplyr使用 dplyr 进行 quasiquotation 的混合输入
【发布时间】:2019-08-06 16:20:54
【问题描述】:

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

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

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

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

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 是我定义了参与规则的表中的字符串列。

例子:

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"))

告诉我找到那些 BMW 为 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)

【问题讨论】:

  • 我在复制/粘贴您的代码时遇到了一些错误。什么是context_col。此外,rules_df 给出错误Error: '\d' is an unrecognized escape in character string starting ""Serie X(\d"
  • 我修复了示例,并完成了复制它的代码。保持它从上到下,遵循逻辑。希望不会太糟糕。
  • 问题是str_detect返回logical和'model'是字符`if_else需要两者是同一个类
  • 您可以使用cars_table %&gt;% mutate(detect = if_else(make == "BMW", as.character(str_detect(model, regex("Serie X\\d"))), model)) 和不使用as.character 进行检查
  • 如果这可以工作,这里期望的输出是什么? R 中的原子向量中不能有混合类型。

标签: r functional-programming dplyr purrr quasiquotes


【解决方案1】:

我们需要用as.character 包装,因为str_detect 返回一个逻辑类,而if_elsefalse 参数返回“字符”。 if_else 是关于这个类的。因此,如果我们这样做

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 

【讨论】:

    猜你喜欢
    • 2011-08-17
    • 2013-07-29
    • 1970-01-01
    • 1970-01-01
    • 2020-02-25
    • 2016-10-13
    • 2021-03-20
    • 2019-01-13
    相关资源
    最近更新 更多