与 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_col
、phrase_col
、target_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_detect
returns一个逻辑class的包装,而if_else
的false
参数是返回 '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
我已经将准报价提升到了最高水平。 我即将获得我的准引用大师徽章(请参阅下面的编辑)。还剩一位挑战者。
使用不同的输入通过 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_col
、phrase_col
、target_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_detect
returns一个逻辑class的包装,而if_else
的false
参数是返回 '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