你如何在R中使用“<< – ”(范围赋值)?
我刚刚读完R介绍的范围,对于这个任务非常好奇。
该手册显示了一个(非常有趣的) <<-
例子,我觉得我明白了。 我仍然缺less的是什么时候这可能是有用的上下文。
所以我喜欢从你那里读到的是关于何时使用<<-
可以是有趣/有用的例子(或者示例的链接)。 什么可能是使用它的危险(看起来很容易疏忽跟踪),以及任何你可能想分享的提示。
<<-
与closures保持联系是最有用的。 这是我最近一篇论文的一部分:
闭包是由另一个函数编写的函数。 闭包被称为是因为它们包含父函数的环境,并且可以访问该函数中的所有variables和参数。 这是有用的,因为它允许我们有两个级别的参数。 一级参数(父级)控制函数的工作方式。 另一个级别(孩子)做这项工作。 下面的例子展示了如何使用这个思想来生成一系列的function函数。 父function( power
)创造孩子function( square
和cube
),实际上做艰苦的工作。
power <- function(exponent) { function(x) x ^ exponent } square <- power(2) square(2) # -> [1] 4 square(4) # -> [1] 16 cube <- power(3) cube(2) # -> [1] 8 cube(4) # -> [1] 64
在两个级别pipe理variables的能力也使得通过允许函数修改其父级环境中的variables来维持函数调用的状态成为可能。 pipe理不同级别variables的关键是双箭头赋值运算符<<-
。 与通常在当前级别上使用的单箭头分配( <-
)不同,双箭头操作符可以修改父级别中的variables。
这样就可以维护一个logging函数被调用的次数的计数器,如下例所示。 每次运行new_counter
,它会创build一个环境,在此环境中初始化计数器i
,然后创build一个新函数。
new_counter <- function() { i <- 0 function() { # do something useful, then ... i <<- i + 1 i } }
新function是闭包,其环境是封闭的环境。 当闭包counter_one
和counter_two
运行时,每一个修改计数器在其封闭环境中,然后返回当前计数。
counter_one <- new_counter() counter_two <- new_counter() counter_one() # -> [1] 1 counter_one() # -> [1] 2 counter_two() # -> [1] 1
它有助于将<<-
等同于assign
(如果将该函数中的inherits
参数设置为TRUE
)。 assign
的好处是它允许你指定更多的参数(比如环境),所以我更喜欢使用<<-
在大多数情况下。
使用<<-
和assign(x, value, inherits=TRUE)
意味着“search提供的环境的封闭环境,直到遇到variables'x'”。 换句话说,它将继续经历这个环境,直到find一个具有这个名字的variables,并且将它分配给它。 这可以在一个函数的范围内,或者在全局环境中。
为了理解这些function的作用,你还需要了解R环境(例如使用search
)。
我经常使用这些function,当我正在运行一个大的模拟,我想保存中间结果。 这允许您创build给定函数或apply
循环范围之外的对象。 这是非常有用的,特别是如果你有任何关于一个大的循环意外结束(例如数据库断开连接)的担心,在这种情况下,你可能会失去过程中的一切。 这相当于在长时间运行的过程中将结果写入数据库或文件,只不过它将结果存储在R环境中。
我的主要警告是:小心,因为你现在正在使用全局variables,特别是在使用<<-
。 这意味着当你期望使用一个作为参数提供的函数时,你最终可能会遇到函数正在使用环境中的对象值的情况。 这是函数式编程试图避免的主要事情之一(见副作用 )。 我通过将我的值赋给一个唯一的variables名称(使用粘贴一组参数或唯一参数)来避免这个问题,这些variables在函数中从来没有使用过,但是只是用于caching,以及在以后需要恢复的时候分析中间结果)。
我使用过的一个地方是使用tcl / tk的简单GUI。 一些最初的例子有它 – 因为你需要在局部和全局variables之间区分statefullness。 看例如
library(tcltk) demo(tkdensity)
它使用<<-
。 否则,我同意马立克:) – 谷歌search可以帮助。
f <- function(n, x0) {x <- x0; replicate(n, (function(){x <<- x+rnorm(1)})())} plot(f(1000,0),typ="l")
在编写参考方法时 , <<-
操作符对于参考类也是有用的。 例如:
myRFclass <- setRefClass(Class = "RF", fields = list(A = "numeric", B = "numeric", C = function() A + B)) myRFclass$methods(show = function() cat("A =", A, "B =", B, "C =",C)) myRFclass$methods(changeA = function() A <<- A*B) # note the <<- obj1 <- myRFclass(A = 2, B = 3) obj1 # A = 2 B = 3 C = 5 obj1$changeA() obj1 # A = 6 B = 3 C = 9
在这个问题上,我想指出的是,<<运算符在for循环中应用(错误)时会performance出奇怪的行为(也可能有其他情况)。 给出以下代码:
fortest <- function() { mySum <- 0 for (i in c(1, 2, 3)) { mySum <<- mySum + i } mySum }
你可能会希望这个函数返回期望的总和6,但是它会返回0,同时创build一个全局variablesmySum
并赋值3.我不能完全解释这里发生了什么,但是肯定是一个for循环不是一个新的范围'级别'。 相反,看起来R看起来在fortest
函数之外,找不到一个mySum
variables来分配,所以创build一个,并且通过循环第一次分配值1。 在后续迭代中,赋值中的RHS必须指的是(不变的)内部mySum
variables,而LHS指的是全局variables。 因此,每次迭代都将覆盖全局variables的值为该迭代的值i
,因此它在退出函数时具有值3。
希望这可以帮助别人 – 今天我困难了几个小时! (顺便说一下,只要用<<replace<<,函数按预期工作)。