R 和 python 一样有断言语句吗?

检查某些内容是否为真以及是否打印给定的错误消息并退出的语句

31824 次浏览

stopifnot()

You may also be interested in packages like Runit and testthat for unit testing.

@Nick:

You can control your error message if you write a function with a descriptive name to test the condition that will throw an error in your program. Here's an example:

Less_Than_8 = function(x) return(x < 8)


for (i in 1:10)
{
print(i)
stopifnot(Less_Than_8(i))
}

This will print the numbers 1 through 8, then print a message that says

Error: Less_Than_8(i) is not TRUE

It would be nice if the "i" in parentheses was replaced with the value that failed the test, but you get what you pay for.

If you need anything fancier than that, look into Runit and testthat as Harlan suggested.

This can be achieved with the stop command. This command will halt the execution of a function and print the error message. For example, we can test if the variable something is FALSE:

if(something == FALSE){
stop("error message to print")
}

Similarly, the warning command will print a warning (but continue executing the code).

if(something == FALSE){
warning("error message to print")
}

These are both provided by base R and require no packages to run or include in writing your own functions. I prefer this approach to write code with fewer dependancies and this syntax is widely used in package development. However, similar functionality is supported by the "assertthat" package with the assert_that function that has recently been released as part of Hadley's "tidyverse".

The testit-package

The testit-package provides the assert-function as a simple solution (https://github.com/yihui/testit)

Examples:

assert('one equals one', 1==1)
assert('seq and : produce equal sequences', seq(1L, 10L) == 1L:10L)
assert('seq and : produce identical sequences', identical(seq(1L, 10L), 1L:10L))


# multiple tests
T=FALSE; F=TRUE
assert('T is bad for TRUE, and so is F for FALSE', T!=TRUE, F!=FALSE)


# a mixture of tests
assert("Let's pray all of them will pass", 1==1, 1!=2, letters[4]=='d', rev(rev(letters))==letters)

Source: https://github.com/yihui/testit/blob/master/R/testit.R

You could use the checkmate-package for that. From one of their examples:

require(checkmate)


fact <- function(n, method = "stirling") {
assertCount(n)
assertChoice(method, c("stirling", "factorial"))


if (method == "factorial")
factorial(n)
else
sqrt(2 * pi * n) * (n / exp(1))^n
}


fact(2, method = 'blub')

The previous responses to this question are quite dated, so I figured I'd add an answer that uses a modern package. The assertr package in R is described well here and documented here. The assertr package makes uses of two primary functions to validate datasets: verify evaluates a boolean expression using the scope of a dataframe passed to it, and will throw, and log the error in the attributes of the dataset if the expression returns FALSE. You can choose to continue processing the dataset if an error is discovered and treat the error much like a warning or you can instruct R to terminate processing. This is useful for verifying dataframe structures and content. For example, using the cars dataset, one might want to verify that it contains 32 rows of data. One could do this with:

library(assertr)
cars %>% verify(nrow(.)==32, error_fun = error_append) %>%
attributes() %>%
pluck("assertr_errors")

The assertr_errors attribute will contain a list of validation errors that did not pass the verify check, so the above would produce the following:

[[1]]
verification [nrow(.) == 32] failed! (1 failure)


verb redux_fn     predicate column index value
1 verify       NA nrow(.) == 32     NA     1    NA

You could also add other verification checks using the assert function as documented in the links below. For example, continuing with the example above, we can verify that no observation in the variable speed exceeds the value of 23:

#Function that returns false if rule fails
is_greater_than_23<-function(x){
x <=23
}


cars %>% assert(is_greater_than_23, speed, error_fun = error_append) %>%
attributes() %>%
pluck("assertr_errors")

Which returns:

[[1]]
Column 'speed' violates assertion 'is_greater_than_23' 5 times
verb redux_fn          predicate column index value
1 assert       NA is_greater_than_23  speed    46    24
2 assert       NA is_greater_than_23  speed    47    24
3 assert       NA is_greater_than_23  speed    48    24
4 assert       NA is_greater_than_23  speed    49    24
5 assert       NA is_greater_than_23  speed    50    25

It's important to note that in the examples above I assigned error_append to the error_fun argument of the verify and assert function calls. This allows R to continue processing the data when the check fails and logs the errors it detected to the assertr_errors attribute. Once you've gathered your errors in this attribute, you can do all sorts of checking and additional verification steps as documented, again, in the links below. If you want the program to stop processing when an error is encountered, you simply change error_append to error_report, which "prints all the information available about the errors in a "tidy" data.frame (including information such as the name of the predicate used, the offending value, etc...) and halts execution."