【问题标题】:Evaluate a function only on a subset of rows in mutate仅在 mutate 中的行子集上评估函数
【发布时间】:2023-03-14 09:53:01
【问题描述】:

有没有办法使用对未包含的行失败的函数在行子集上mutate

我正在尝试使用my_func,但对于某些值(下面的玩具示例中的5)失败。我可以在某些行而不是其他行上评估此函数,为其他行返回 NA 吗?我尝试使用if_else,但它会评估所有值的函数,导致它失败:

my_func = function(x) {
  if (any(x == 5)) stop("Fail!")
  return(x + 1)
}

data.frame(value = c(1, 5, 2)) %>%
  mutate(result = if_else(value == 5, NA, my_func(value)))

我可以围绕 my_func 构建一个包装器,以删除破坏值,然后在返回之前将这些值插入到 my_func 的返回值中,但这似乎过于复杂。

更新:解决方案不得更改my_func!我最近遇到了这个问题,my_funcquantreg::predict.rqss

【问题讨论】:

  • 对于 NA 值,您可以显式检查 NA。 if_else(is.na(value) || value == 5, NA, my_func(value))。它失败的其他值有哪些示例?
  • @rpolicastro 尝试运行您的建议。它仍然评估 my_func 的所有值,因此失败。

标签: r dplyr subset


【解决方案1】:

这是一个解决方案:

eval_subset = function(x, fun, subset, false = NA) {
  x[subset] = fun(x[subset])  # Apply fun to values where subset == TRUE
  x[!subset] = false  # Insert default values else
  return(x)
}

像这样使用它:

data.frame(value = c(1, 5, 2)) %>%
  mutate(result = eval_subset(value, my_func, value != 5))

这对我的口味来说有点麻烦。希望有更多内置的东西,但它可以工作。

【讨论】:

    【解决方案2】:

    my_func 中使用ifelse,以便它可以处理向量值。

    my_func = function(x) {
      ifelse(is.na(x), NA, x + 5)
    }
    

    现在您可以将其用作:

    data.frame(value = c(NA, 1, 2)) %>%
      mutate(result = my_func(value))
    

    这也返回相同的输出,所以你真的不需要在这里检查NAs。

    data.frame(value = c(NA, 1, 2)) %>% mutate(result = value + 5)
    

    如果我们不能真正更改 my_func 测试条件和 NA 明确:

    my_func = function(x) {
      if (is.na(x) || x == 5) return(NA)
        else return(x + 1)
    }
    

    并按行应用函数:

    data.frame(value = c(NA, 1, 2)) %>%
      rowwise() %>%
      mutate(result = my_func(value))
    

    【讨论】:

    • 我更新了问题以强调我无法更改my_func。因此,不幸的是,您的解决方案不适用。我还更新了它,使其值 5 失败,这样在许多情况下,人们不会被 R 对 NA 的固有处理所吸引。
    • 您还在更新中更改了my_func。再说一次,我不能那样做。但我想你可以使用包装函数做同样的事情。我已经发布了一个答案,这个答案是矢量化的,所以它比rowwise 使用起来更快/更简单。我一直在寻找更原生于 dplyr 或其他软件包的东西,因为这似乎是一个不太罕见的用例。
    猜你喜欢
    • 2014-09-14
    • 2014-05-19
    • 1970-01-01
    • 1970-01-01
    • 2021-10-04
    • 2021-07-23
    • 1970-01-01
    • 2021-04-13
    • 1970-01-01
    相关资源
    最近更新 更多