如何将函数体中定义的变量用作该函数的参数?

时间:2018-02-04 04:24:03

标签: r

我正在解决这个问题:第一个人掷出3个中的1个,然后第二个人掷出剩下的2个骰子中的1个。骰子是6面的,但每侧有随机数字(对应于每个骰子的数字都列在该骰子的样本中)。

approximated.probability.that.c1.wins <- function(n, k, c1, c2){

    red <- replicate(k, sum(sample(c(3,3,3,3,3,6), n)))
    yellow <- replicate(k, sum(sample(c(2,2,2,5,5,5), n)))     
    green <- replicate(k, sum(sample(c(1,4,4,4,4,4), n))) 

    return(sum(c1 > c2))
}

approximated.probability.that.c1.wins(1, 1000, red, green)

当我将c1c2替换为sum(red > green)等函数中的向量时,我的函数有效。但是,当我按原样运行该函数时,它返回错误"object 'red' not found"。目标是用调用函数时定义的任何颜色替换c1c2

3 个答案:

答案 0 :(得分:1)

您尝试做的事情是相当高级的R.请注意,redgreen未在您的父框架中定义,因此在常规编程中,这不起作用。但是,如果将它们捕获为表达式,然后在redgreenyellow存在后进行评估,它确实有效。这是一种方法:

library(rlang)
approximated.probability.that.c1.wins <- function(n, k, c1, c2){
  c1 <- enexpr(c1)
  c2 <- enexpr(c2)

  red <- replicate(k, sum(sample(c(3,3,3,3,3,6), n)))
  yellow <- replicate(k, sum(sample(c(2,2,2,5,5,5), n)))     
  green <- replicate(k, sum(sample(c(1,4,4,4,4,4), n))) 

  # note: added divide by k to calculate probability
  return(sum(eval(c1) > eval(c2))/k)
}

set.seed(1234)
approximated.probability.that.c1.wins(1, 1000, red, green)
[1] 0.299

答案 1 :(得分:1)

我们可以使用base R执行此操作,方法是将其作为字符串传递,然后使用get获取值

approximated.probability.that.c1.wins <- function(n, k, c1, c2){

   red <- replicate(k, sum(sample(c(3,3,3,3,3,6), n)))
   yellow <- replicate(k, sum(sample(c(2,2,2,5,5,5), n)))     
    green <- replicate(k, sum(sample(c(1,4,4,4,4,4), n))) 

   return(sum(get(c1) > get(c2)))
}

approximated.probability.that.c1.wins(1, 3, 'red', 'green')

答案 2 :(得分:1)

非标准评估

创建由Lredyellow这三个组成部分组成的列表green。 然后,指示的表达式可用于转换非标准输入 字符串,用于在L中查找适当的组件。

approximated.probability.that.c1.wins <- function(n, k, c1, c2){

    L <- list(red = replicate(k, sum(sample(c(3,3,3,3,3,6), n))),
              yellow = replicate(k, sum(sample(c(2,2,2,5,5,5), n))),
              green = replicate(k, sum(sample(c(1,4,4,4,4,4), n))))

    c1 <- deparse(substitute(c1))  ## 
    c2 <- deparse(substitute(c2))  ##

    sum(L[[c1]] > L[[c2]])
}

approximated.probability.that.c1.wins(1, 1000, red, green)

标准评估

要使用标准评估(而不是上面使用的非标准),我们会通过"red""green"而不是redgreen,然后我们就不再需要上面标有##的两行,所以代码简化为:

approximated.probability.that.c1.wins <- function(n, k, c1, c2){

    L <- list(red = replicate(k, sum(sample(c(3,3,3,3,3,6), n))),
              yellow = replicate(k, sum(sample(c(2,2,2,5,5,5), n))),
              green = replicate(k, sum(sample(c(1,4,4,4,4,4), n))))

    sum(L[[c1]] > L[[c2]])
}

approximated.probability.that.c1.wins(1, 1000, "red", "green")

使用环境

虽然通常最好不要使用环境,但定义L的替代方法是使用问题中的原始代码,但用以下内容替换正文的最后一行:

e <- environment()
sum(e[[c1]] > e[[c2]])

e包含当前函数中的所有变量。这适用于标准评估部分以及使用标记为##。

的行的非标准评估