【问题标题】:How to report error indices in R? [closed]如何报告 R 中的错​​误索引? [关闭]
【发布时间】:2018-02-02 21:49:21
【问题描述】:

更新:这里的问题已经结束,现在在RStudio Community Platform 讨论。


我正在尝试program defensively 在我的包开发中,使用大量输入验证。 特别是,我依赖于checkmatetestthat 等中的许多现成断言,这让生活变得更轻松(并且代码更短)。

Hadley Wickhams 的 tidyverse style guide for error messages 建议错误消息应将用户指向问题的确切根源,如下所示:

#> Error: Can't find column `b` in `.data`

(列只是一个例子,有时它可能是行或其他索引)。

我现在想知道如何在一个包中优雅且一致地实现这一点,因为许多现有的断言(来自上述包,但也包括基础 r)不会在错误中返回任何索引。

这是一个例子:

m <- matrix(data = c(0, 1, 5, -2), nrow = 2)

# arbitrary assertion
assert_positive <- function(x) {
  if (any(x < 0)) {
    stop(call. = FALSE,
         "All numbers must be non-negative")
  } else {
    return(invisible(x))
  }
}
# (there are *lots* of these in packages such as checkmate, testthat or assertr that should be reused)

assert_positive(m)

给予:

## Error: All numbers must be non-negative

到目前为止一切都很好,但这并没有给出所需的错误索引。

是的,我知道我可以更改上面的assert_positive() 函数来做到这一点,但我想重用checkmatetestthat 和朋友中的很多函数,所以我不能碰它们,反正它们太多了。

所以我可能应该包装这些现有的测试,比如一个简单的 for 循环:

# via for-loops
assert_positive2 <- function(x) {
  for (r in 1:nrow(x)) {
    res <- try(expr = assert_positive(x[r, ]), silent = TRUE)
    if (inherits(x = res, what = "try-error")) {
      stop(
        call. = FALSE,
        paste0(
          "in row ",
          r,
          ": ",
          attr(x = res, which = "condition")$message,
          "."
        )
      )
    }
  }
}

assert_positive2(m)

给予:

## Error: in row 2: All numbers must be non-negative.

这样就完成了工作,但是它很混乱,而且代码的表达能力也不是很强。 我也考虑过Reduce()try(),但这不会给出索引,任何apply() 操作也不会。 我想,最后,闭包或函数工厂将有助于将其推广到许多断言。

这感觉就像许多其他人(制作更好的错误消息)必须已经遇到的问题,所以:

什么是优雅/规范的方法?

我知道这里不是讨论和发表意见的地方;但它仍然是解决此类问题的最佳论坛,所以请不要关闭它

【问题讨论】:

  • 我已经在RStudio Community Forum 上发布了这个问题,毕竟这可能是进行这种公开讨论的更好地方。随意关闭。

标签: r error-handling assert tidyverse defensive-programming


【解决方案1】:

我看不出包装许多函数会比仅仅更改它们/编写自己的版本更少工作。另外,就像你说的,你包装这个例子的方式一点也不可爱。

作为一个简短的回答,我可以想象使用assertthat 包(您没有明确提及),特别是函数assert_that()(用于基本情况)和on_failure()(用于更广泛的用户定义的断言函数)。

我认为assert_positive 示例不能满足您的要求,因此您可能不应该尝试回收它。同样,assert_positive2 在其他情况下也可能不会执行您想要的操作,因为您可能希望报告每行违规的特定索引,而不仅仅是行。但是使用您自己的函数,您也许可以编写更灵活的内容,涵盖多种情况。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-08-22
    • 2020-11-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-15
    • 1970-01-01
    相关资源
    最近更新 更多