使用R中的NSE进行信息性的“stopifnot()”错误

时间:2017-04-13 14:57:26

标签: r non-standard-evaluation

我想提供有用的stopifnot()错误。

我读过:  http://r-pkgs.had.co.nz/tests.html(最后一节使用NSE打印信息测试错误的示例似乎相关) 和 http://adv-r.had.co.nz/Computing-on-the-language.html 但是我无法通过简洁的代码打印信息错误:

e <- new.env()
e$label <- c(1,2,3)
check_in_y <- function(x, z, e) {
  stopifnot(eval(bquote(.(x) %in% e[[.(z)]])))
}

check_in_y(5,"label", e)

输出给出了这个(不那么有用)

  

错误:eval(bquote(。(x)%in%e [[。(z)]]))不为TRUE

我希望错误提供更多信息,并说:

  

错误:%e [[&#34;标签&#34;]]中的5%不为真

我怎样才能让它发挥作用?或者什么是实现我想要的最佳方法

我知道我可以写一个if条件不是真的然后打印我自己的错误作为替代,但额外的代码是一个麻烦。我想了解如何让NSE让它发挥作用。

编辑: 我从这种方法中获得的动机来自阅读hadley的评论(http://r-pkgs.had.co.nz/tests.html):

  

然而,如果期望失败,这并不能提供非常丰富的信息   输出:

expect_floor_equal("year", "2008-01-01 00:00:00")
## Error: floor_date(base, unit) not equal to as.POSIXct(time, tz = "UTC")
## Mean absolute difference: 31622400
     

相反,您可以使用一些非标准的评估来制作   一些更丰富的信息。关键是使用bquote()和eval()。在   下面的bquote()调用,注意使用。(x) - ()的内容   将被插入通话中。

expect_floor_equal <- function(unit, time) {
  as_time <- function(x) as.POSIXct(x, tz = "UTC")
  eval(bquote(expect_equal(floor_date(base, .(unit)), as_time(.(time)))))
}
expect_floor_equal("year", "2008-01-01 00:00:00")
## Error: floor_date(base, "year") not equal to as_time("2008-01-01 00:00:00")

2 个答案:

答案 0 :(得分:4)

stopifnot只是

的便利功能
if(!all(condition)) stop(standard message)

对于自定义消息,只需编写代码即可。您可以用两行代替stopifnot来电:

check_in_y <- function(x, z, e) {
    b <- bquote(.(x) %in% e[[.(z)]])
    if(!eval(b)) stop(deparse(b), " is not TRUE", call. = FALSE)
}

check_in_y(5, "label", e)
# Error: 5 %in% e[["label"]] is not TRUE

答案 1 :(得分:4)

CRAN上有许多软件包可以解决有意义的错误消息问题。我已经开始使用assertthatassertive包,但我现在使用checkmate来生成代码,尤其是检查函数的参数。顺便说一句,checkmate也扩展了Hadley的testthat包。

使用checkmate

checkmate::assert_choice(5, e[["label"]])

返回错误消息:

  

checkmate :: assert_choice错误(5,e [[“label”]]):
    断言'5'失败:必须是集{'1','2','3'}的元素。

它也可以用在函数

check_in_y <- function(x, z, e) {
  checkmate::assert_choice(x, e[[z]])
}
check_in_y(5, "label", e)

返回相同的错误消息。