【问题标题】:Correctly using rlang::as_function formula within .predicate argument of mutate_if在 mutate_if 的 .predicate 参数中正确使用 rlang::as_function 公式
【发布时间】:2019-01-15 17:11:30
【问题描述】:

我想以下列方式在mutate_if.predicate 参数中使用~ . %% 1 == 0 公式:

dta %>%
    mutate_if(.predicate =  ~ . %% 1 == 0,
              .funs = funs(. + 10))

其中dta 对应于以下小标题:

dta <- tibble(colA = c("a", "b"),
              colB = 1:2,
              colC = c(1.1, 2.2))

这当前会产生以下错误:

.%%1 中的错误:二元运算符的非数字参数

背景

dplyr::mutate_if 的文档中声明:

.predicate 应用于列的谓词函数或 逻辑向量。 .predicate 为或返回 TRUE 的变量 被选中。这个参数被传递给rlang::as_function(),因此 支持quosure风格的lambda函数和字符串表示 函数名。

因此,公式~ . %% 1 == 0 可以按以下方式使用:

f_rlang_check <- rlang::as_function( ~ . %% 1 == 0)

f_rlang_check(c(1.1, 1))
[1] FALSE  TRUE

显然公式是正确的;但是它不能直接传递给rlang::as_function(),如上所示。

dta %>%
    mutate_if(.predicate = f_rlang_check,
              .funs = funs(. + 10))

产生相同的错误

【问题讨论】:

    标签: r dplyr rlang


    【解决方案1】:

    mutate_if 将尝试评估所有列的谓词函数,因此在尝试将二元运算符 %% 与非数字参数 colA 一起使用时会出错。您可以使用is.numeric&amp;&amp; 解决此问题。

    谓词应返回单个逻辑值,因此您可能需要使用allany

    dta %>%
        mutate_if(.predicate = ~ is.numeric(.) && all(. %% 1 == 0),
                  .funs = funs(. + 10))
    

    【讨论】:

    • 非常感谢,现在我知道是什么问题了。为什么您决定使用&amp;&amp; insetad of &amp;,如果只关注比较第一个值或使用.predicate 时总是逐一比较存在错误结果的风险?
    • 如果你使用&amp;,那么&amp;的两边都会被计算,在这种情况下会产生错误。使用&amp;&amp;,仅当 LHS 为 TRUE 时才评估 RHS(如果是 FALSE,则总结果为 FALSE,因此无需检查 RHS)文档中的一种非显而易见的方式是“评估仅在确定结果之前进行。”
    • 太好了,非常感谢。
    猜你喜欢
    • 1970-01-01
    • 2017-06-22
    • 1970-01-01
    • 2021-04-08
    • 1970-01-01
    • 1970-01-01
    • 2021-04-09
    • 2019-04-15
    • 1970-01-01
    相关资源
    最近更新 更多