【问题标题】:Why does <<- assignment work in my function, but <- doesn't? [duplicate]为什么 <<- 赋值在我的函数中起作用,但 <- 不起作用? [复制]
【发布时间】:2018-12-13 22:06:23
【问题描述】:

我试图在实践中了解&lt;-&lt;&lt;- 之间的区别。我在R 中编写了以下函数,它依赖于我编写的其他几个小函数:

fun.exec <- function(x=dat){
  id1 <- prompt1()
  id2 <- prompt2()
  el.type <- data.switch(di=id1)
  dat.sifted <- data.sift(x, nc=id2)
  plots.list <- evol.tiles(ds=dat.sifted, dt=el.type, nc=id2)
  p <- evol.plot(l=plots.list, dt=el.type)
}

函数prompt1prompt2 接受用户输入,el.type() 为数据分配字符串名称(用于自动描述不同的图),data.sift() 从大数据框对象中提取相关数据, evol.tiles() 生成各种 ggplots 以组织在一个网格中,evol.plot() 将这些图放在一个网格中。

可以看出,data.sift()evol.tiles() 函数都使用id2 用户的输入。当我按原样执行此函数时,出现错误:

Error in evol.tiles(ds = dat.sifted, dt = el.type, nc = id2) : object 
'id2' not found 

如果我将id2 &lt;- prompt2() 替换为id2 &lt;&lt;- prompt2(),代码将按预期工作。

我不明白为什么data.sift() 函数上的代码没有中断,该函数也需要id2。我阅读了help 的作业、StackOverflow 上的一些相关帖子以及An Introduction to RScope 部分,但我仍然不确定问题出在哪里。就好像在 data.sift() 中使用后,该变量在环境中不再可用,我不明白那是。

任何帮助将不胜感激。

更新: 下面是提示代码:

prompt1 <- function(){
  cat('What do you want to create plots for? Your options are:
        1: data type A,
        2: data type B,
        3: data type C')
  readline(prompt="Enter an integer: ")
}

prompt2 <- function(){
  cat('How many nodes do you want to visualize?')
  n <- readline(prompt="Enter an integer: ")
  cat('\nProvide coordinates of each node to visualize separated by commas.')
  l <- vector("list", n)
  for (i in 1:n){
    el <- readline(prompt=paste('Enter coordinnates for node',i,': '))
    l[[i]] <- el
  }
  return(l)
}

对于data.sift()

data.sift <- function(x, nc){
  nl <- lapply(nc, function(l){as.integer(unlist(strsplit(l,",")))})
  ds <- vector("list", length(nl))
  for (i in 1:length(nl)){
    ds[[i]] <- x[(x$x == nl[[i]][1] & x$y == nl[[i]][2] & x$z == nl[[i]][3]),]
  }
  return(ds)
}

对于evol.tiles()

evol.tiles <- function(ds, dt, nc){
  require(ggplot2)
  my.cols <- rainbow(length(ds))
  my.names <- as.character(nc)
  names(my.cols) <- my.names

  my.list <- list()
  for (i in 1:6){
    for (ii in 1:length(id2)){
      p <- ggplot(NULL, aes_(x = as.name(names(ds[[ii]][4]))))
      p <- p + geom_line(data = ds[[ii]], 
                         aes_(y = as.name(names(ds[[ii]][i])), 
                              colour = as.character(nc[[ii]])))
    }
    p <- p  + scale_colour_manual("Node",
                          breaks = as.character(nc),
                          values = my.cols)
    my.list[[i-dr[1]+1]] <- p
  }
  return(my.list)
}

【问题讨论】:

  • “我正在尝试理解 <<-。
  • 这真的很好奇。我认为你不应该使用&lt;&lt;-,但是你得到这个错误是很奇怪的。 id2 绝对应该可用。不知道如何在没有看到更多代码的情况下解决这个问题。你在data.siftevol.tiles 中做了什么奇怪的事情?
  • 请用所有必要的信息更新您的问题,以便我们更好地了解问题可能是什么。现在它只是一个猜谜游戏。 See also the info on how to give a reproducible example.
  • 这是标题中的问题明显重复的情况之一(可以说,应该这样关闭)但问题的主体涉及不重复的内容。我愿意投票重新打开它,但认为应该更改标题以反映实际问题(其本身应扩展为包含minimal reproducible example)。
  • 尝试发布不同的函数并删除所有不需要重现问题的代码。然后给出最简单的数据集来重现。目前这只是一个猜谜游戏,问题可能会因为不可重现而再次关闭。

标签: r assignment-operator


【解决方案1】:

正如在 cmets 中发布的那样,我认为我发现了问题 - 在处理一个最小的工作示例时,我发现在我的函数 evol.tiles() 中我调用了 id2 变量而不是 nc(在内部循环中)。我想当我将&lt;&lt;- 用于prompt2() 时,我被全局分配了它,然后当从evol.tiles() 中调用它时可以找到它,但是&lt;- 它对evol.tiles() 不可用。

即便如此,我还是不太明白为什么会这样。我认为该函数应该在育儿环境中查找缺少的参数,并且由于id2 是在fun.exec() 中定义的,time.evol() 应该能够找到正确的值。

这是一个简单的示例,展示了我期望代码的行为方式,即使在我的例子中使用了一个错误命名的变量:

test <- function(){x*x}
test()
Error in test() : object 'x' not found

如果我自己运行 test() 函数,我会得到与我的函数相同的错误,这正是我所期望的。但是,如果我将值分配给x,即,

x <- 2
test()
[1] 4 

该功能运行良好。有人能告诉我为什么我的函数的行为方式不同吗?

更新: @Aaron:你给出的例子,即rm(x); test2 &lt;- function() { x &lt;- 2; test() }; test2(),对我来说执行得很好:

所以我还是不明白问题是什么。有什么想法吗?

【讨论】:

  • 嗨 Justyna,我认为此时最好关闭这个问题并打开一个新问题,这个问题有很多包袱,你发现对手头的问题并不重要.如果您选择这样做,我认为您还需要一个 MCVE;也就是说,在另一个函数中,test 在分配 x 后并没有按照您的预期执行,如下所示:rm(x); test2 &lt;- function() { x &lt;- 2; test() }; test2()
  • 其实我认为这个问题是stackoverflow.com/q/18338331/210673的重复;尽管那里的答案相当技术性。或者stackoverflow.com/q/44427752/210673;这个问题不太相似,但我认为答案可能更合适。特别是,它查看的是封闭环境,而不是父环境。
  • @Aaron 感谢您的参考。帖子和其中的参考资料都非常有帮助!我认为我不需要发布关于它的新问题。再次感谢您!
猜你喜欢
  • 2021-05-05
  • 2019-04-01
  • 2018-10-27
  • 2019-10-06
  • 2013-08-24
  • 1970-01-01
  • 1970-01-01
  • 2020-07-04
  • 2018-04-06
相关资源
最近更新 更多