Combining logical functions in R

时间:2018-02-03 09:47:35

标签: r

I'm running several tests for a given object x. For a given test (being a test a function that returns TRUE or FALSE when applied to an object) it is quite easy, as you can do lapply(x, test). For example:

# This would return TRUE
lapply('a', is.character)

However, I would like to create a function pass_tests, which would be able to combine multiple tests, i.e. that it could run something like this:

pass_tests('a', is.character | is.numeric)

Therefore, it should combine multiple functions given in an argument of the function, combining its result when testing an object x. In this case, it would return whether 'a' is character OR numeric, which would be TRUE. The following line should return FALSE:

pass_tests('a', is.character & is.numeric)

The idea is that it could be flexible for different combinations , e.g.:

pass_tests(x, test1 & (test2 | test3))

Any idea if functions can be logically combined this way?

2 个答案:

答案 0 :(得分:3)

Another option would be to use the pipes

library(magrittr) # or dplyr
"a" %>% {is.character(.) & is.numeric(.)} 
#FALSE
"a" %>% {is.character(.) | is.numeric(.)} 
#TRUE

1 %>% {is.finite(.) & (is.character(.) | is.numeric(.))} 
#TRUE

Edit: used in a function with string

pass_test <- function(x, expr) {

  x %>% {eval(parse(text = expr))}
}

pass_test(1, "is.finite(.) & (is.character(.) | is.numeric(.))")
#TRUE

The argument expr can be a string or an expression as in expression(is.finite(.) & (is.character(.) | is.numeric(.))).

答案 1 :(得分:1)

Here's another way to do it by creating infix operators.

`%and%` <- function(lhs, rhs) {
  function(...) lhs(...) & rhs(...)
}

`%or%` <- function(lhs, rhs) {
  function(...) lhs(...) | rhs(...)
}


(is.character %and% is.numeric)('a')
#> [1] FALSE

(is.character %or% is.numeric)('a')
#> [1] TRUE

These can be chained together. However, it will not have the normal AND/OR precedence. It will be evaluated left-to-right.

(is.double %and% is.numeric %and% is.finite)(12)
#> [1] TRUE