【问题标题】:Why doesn't this R function work?为什么这个 R 函数不起作用?
【发布时间】:2016-09-30 16:22:12
【问题描述】:

我创建了以下函数来将新字符串附加到一个名为“meals”的字符串向量上。但是,当我使用此函数将字符串输入附加到我的“膳食”向量中时,它不起作用。

 add <- function(str) {
      meals <- append(meals, as.character(str))  
    }

【问题讨论】:

  • 这两个 cmets 都没有抓住重点。该功能将起作用,但需要以功能方式应用,即:meals &lt;- add( c("lunch", "dinner") )
  • 因为它会返回 append 调用的值。试试看?'&lt;-'
  • 我质疑搁置这个问题。这不是一个错字。无法理解 R 函数如何返回值,正如至少 2 位评论者(他们现在已经删除了他们的 cmets)所展示的那样,以及也错过了这方面的两个答案所展示的。它可以作为一个有用的例子,但现在关闭似乎正在把它扫到地毯下。仅仅因为提问者不明白这一点,这并不意味着它是一个微不足道的问题。这实际上是一个相当深奥的问题,其正确答案表明了 R 与大多数其他计算机语言之间的根本区别。

标签: r


【解决方案1】:

这里的问题是变量范围。变量meals 存在于您使用它的全局环境中。运行函数时,函数环境中没有 meals 变量,因此它从全局环境中继承了该变量。但是,当它修改变量时,它会在函数环境内部创建一个新版本。然后该函数可以使用修改后的版本,但它永远不会更改全局环境中的 meals 变量。

因此,您可以使用当前编写的函数,并将结果保存到meals,如下所示:

meals <- add("Steak")

当您将其保存到函数末尾的变量时,该值会以不可见的方式返回,但它仍然会输出(如 lmhist 的完整结果,只有将它们保存到新变量)。这就是为什么养成使用明确的 returninvisible 语句结束函数的习惯是个好主意的原因之一。

我的猜测是您来自不同的编程语言,其中更改函数内部的全局变量会全局更改变量。通过明确告诉 R 使用 &lt;&lt;- 覆盖该环境行为来实现该行为,该行为将值分配到当前环境之外(而不是仅在其中)。例如,这个:

add <- function(str) {
  meals <<- append(meals, as.character(str))  
}

meals <- "Steak"

add("Chicken")

meals

导致meals 同时持有“牛排”和“鸡肉”——这是您想要的行为。 但是,这在 R 中通常是一个坏主意。有时这种行为很好,但事实上它与 R 的一般操作方式非常不同,这给错误留下了很多机会. 我偶尔会使用它来解决范围界定问题(通常在 shiny 工作并需要为整个会话更改内容时,而不仅仅是当前用户),但我尽量避免它。

我鼓励你改用这个结构:

meals <- append(meals, str)

直接,而不是尝试将其包装在与标准 R 方法完全不同的自定义函数中。

【讨论】:

    【解决方案2】:

    它怎么不工作?

    需要考虑的一点:函数的输出是函数的最后一行。例如:

    x.plus.3 <- function(x){
            s <- x+3
    }
    x.plus.3(2)
    #  nothing is printed
    

    这是一个有效的函数,但如果运行将没有输出,因为该函数所做的只是将 x+3 存储到对象 s 中。

    但是,如果,我将其更改为:

     x.plus.3 <- function(x){
             s <- x+3
             s
     }
     x.plus.3(2)
    [1] 5  # i get the result printed
    

    因此,您需要在函数的最后一行添加餐点,以使其位于函数之外。

    【讨论】:

      【解决方案3】:

      您需要确保在您的情况下将要输出的函数分配给变量尝试以下方法(3 种可能的解决方案):

      ## longest/redundant
      add <- function(str) {
         meals <- append(meals, as.character(str))
         return(meals)
      }
      
      ## alternative
      add2 <- function(str) {
         meals <- append(meals, as.character(str))
      }
      
      ## simplest
      add3 <- function(str) {
         append(meals, as.character(str))
      }
      
      meals <- c("chx","beef","pork")
      str1 <- c(1, 2, 3)
      
      newVar <- add(str1)
      print(newVar)
      [1] "chx"  "beef" "pork" "1"    "2"    "3"  
      
      newVar2 <- add2(str1)
      print(newVar2)
      [1] "chx"  "beef" "pork" "1"    "2"    "3"  
      
      newVar3 <- add3(str1)
      print(newVar3)
      [1] "chx"  "beef" "pork" "1"    "2"    "3"  
      

      您也可以考虑一个更简单的解决方案:

      c(meals, str1) 将返回完全相同的内容。 append 通常仅在您需要使用 after 参数时使用。

      【讨论】:

      猜你喜欢
      • 2021-06-14
      • 1970-01-01
      • 1970-01-01
      • 2011-07-25
      • 1970-01-01
      • 2020-04-02
      • 2021-10-28
      • 2013-04-04
      • 1970-01-01
      相关资源
      最近更新 更多