Home > OS >  How to write a if else function in R to generate rule?
How to write a if else function in R to generate rule?

Time:11-29

I wanna print the rule like following: 
rule(0,0,0) = 0
rule(0,0,1) = 1
rule(0,1,0) = 1
rule(0,1,1) = 1
rule(1,0,0) = 1
rule(1,0,1) = 0
rule(1,1,0) = 0
rule(1,1,1) = 0

I tried to write a set of “if-else” conditions that test for zeroes and ones in the input values, returning the corresponding value from the table as output but it didnt work

CodePudding user response:

A single comparison will do. This would be the most performant implementation I can think of.

rule <- function(a, b, c)  (abs(4*a   2*b   c - 2.5) < 2)

A parsimonious solution:

rule <- function(a, b, c)  xor(a, b | c)

Note both solutions are vectorized.

Benchmarking:

rule1 <- function(a, b, c)  (abs(4*a   2*b   c - 2.5) < 2)
rule2 <- function(a, b, c)  xor(a, b | c)
rule3 <- function(x, y, z)  ((4 * x   2 * y   z) %in% 1:4)

abc <- matrix(sample(0:1, 3e6, 1), 1e6, 3)

microbenchmark::microbenchmark(rule1 = rule1(abc[,1], abc[,2], abc[,3]),
                               rule2 = rule2(abc[,1], abc[,2], abc[,3]),
                               Thomas = rule3(abc[,1], abc[,2], abc[,3]),
                               check = "identical")
#> Unit: milliseconds
#>    expr     min       lq     mean   median       uq     max neval
#>   rule1 13.5161 16.58425 20.74505 17.69030 20.22745 53.9513   100
#>   rule2 32.7552 35.05735 39.41473 36.27760 39.38165 74.8564   100
#>  Thomas 24.6562 28.39065 33.78937 29.70875 33.19045 65.9709   100

CodePudding user response:

A possibility is to concatenate the three digits and then use switch:

rule <- function(a, b, c) {
  x <- paste0(a, b, c)
  switch(
    x,
    "000" = 0,
    "001" = 1,
    ......
  )
}

CodePudding user response:

You can try

rule <- function(x, y, z) {
   ((4 * x   2 * y   z) %in% 1:4)
}

or

rule <- function(x, y, z) {
  bitwXor(x, bitwOr(y, z))
}

Benchmark

rule1 <- function(a, b, c)  (abs(4 * a   2 * b   c - 2.5) < 2)
rule2 <- function(a, b, c)  xor(a, b | c)
rule3 <- function(x, y, z)  ((4 * x   2 * y   z) %in% 1:4)
rule4 <- function(x, y, z) bitwXor(x, bitwOr(y, z))

abc <- matrix(sample(0:1, 3e6, 1), 1e6, 3)

microbenchmark::microbenchmark(
  rule1 = rule1(abc[, 1], abc[, 2], abc[, 3]),
  rule2 = rule2(abc[, 1], abc[, 2], abc[, 3]),
  Thomas1 = rule3(abc[, 1], abc[, 2], abc[, 3]),
  Thomas2 = rule4(abc[, 1], abc[, 2], abc[, 3]),
  check = "identical"
)

gives

Unit: milliseconds
    expr     min       lq     mean   median       uq      max neval
   rule1 16.1315 22.82880 32.91071 24.48080 28.29635 113.1915   100
   rule2 33.6093 40.93665 50.12914 44.77415 48.90045 128.0033   100
 Thomas1 26.6938 34.78615 43.34770 37.63255 42.49940 114.3973   100
 Thomas2  9.1119 12.25080 18.46705 16.26445 18.46835 105.1263   100

CodePudding user response:

In the case that your rule can't be expressed as a mathematical expression (as jblood94 and ThomasIsCoding did), you can create a list with the options, check which option was passed, and get the result associated with that option.

rule = function(n1, n2, n3){
  combin = list(c(0,0,0), c(1,0,0), c(0,1,0), c(0,0,1), c(1,1,0), c(1,0,1), c(0,1,1), c(1,1,1))
  result = c(0, 1, 1, 1, 0, 0, 1, 0)
  
  index = which(sapply(combin, function(x){identical(x, c(n1, n2, n3))}))
  result[index]
}

rule(0, 1, 0)
[1] 1

CodePudding user response:

For the fun of brevity:

rule <- function(first, second, third){
    bits_as_decimal = paste(first, second, third, sep = '') |>
        strtoi(base = 2)
    bits_as_decimal %in% 1:4 |> as.integer()
}

What happens:

  • the three arguments are considered a three bit binary (e. g. 001)
  • binary gets converted to its decimal equivalent (strtoi)
  • check if the decimal equivalent falls into the range 1-4 (which you want to convert to 1)
  • re-cast the boolean value to binary
  •  Tags:  
  • r
  • Related