如何在R中编写if else函数来生成规则?

agyaoht7  于 2022-12-06  发布在  其他
关注(0)|答案(5)|浏览(138)
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

我尝试编写一组“if-else”条件,用于测试输入值中的0和1,并从表中返回相应的值作为输出,但没有成功

yb3bgrhw

yb3bgrhw1#

一个简单的比较就可以了。这将是我能想到的性能最好的实现。

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

节俭的解决办法:

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

请注意,两种解决方案都是矢量化的。
基准测试:

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
ppcbkaq5

ppcbkaq52#

一种可能性是将这三个数字连接起来,然后使用switch

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

mkh04yzy3#

你可以试试

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

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

性能指标评测

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"
)

给予

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
voj3qocg

voj3qocg4#

如果您的规则不能表示为数学表达式(如jblood94和ThomasIsCoding所做的那样),您可以创建一个包含选项的列表,检查传递了哪个选项,并获得与该选项关联的结果。

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
bis0qfac

bis0qfac5#

为了简洁起见:

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

发生的情况:

  • 三个自变量被认为是三位二进制(例如001)
  • 二进制转换为十进制(strtoi
  • 检查十进制等效值是否在1-4范围内(您要将其转换为1)
  • 将布尔值重新转换为二进制

相关问题