【问题标题】:How can I use variables defined in the body of a function as argument to that function?如何使用函数体中定义的变量作为该函数的参数?
【发布时间】:2018-02-04 04:24:03
【问题描述】:

我正在解决这个问题:第一个人掷出 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 &gt; green))时,我的函数工作。但是,当我按原样运行该函数时,它返回错误"object 'red' not found"。目标是用我在调用函数时定义的任何颜色替换c1c2

【问题讨论】:

  • 如果在函数运行之前没有创建 red 对象(并且无论如何只能在函数的环境中),则不能使用 red 调用它。该函数也不对 red/yellow/green 变量做任何事情,这可能不是您想要的。
  • 你可能需要approximated.probability.that.c1.wins(1, 3, 'red', 'green')return(sum(get(c1) &gt; get(c2)))
  • @akrun 或将c1c2 捕获为表达式。

标签: r


【解决方案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

【讨论】:

    【解决方案2】:

    我们可以使用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')
    

    【讨论】:

      【解决方案3】:

      非标准评价

      创建由redyellowgreen 三个组件组成的列表L。 然后可以使用指示的表达式来转换非标准输入 用于在 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 包含当前函数中的所有变量。这将适用于标准评估部分,也适用于使用标记为 ## 的行的非标准评估。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-12-28
        • 2018-10-28
        • 1970-01-01
        • 2023-03-22
        • 1970-01-01
        • 2014-06-07
        • 1970-01-01
        • 2012-03-20
        相关资源
        最近更新 更多