`[<-` 函数在 R 中如何工作?

Posted

技术标签:

【中文标题】`[<-` 函数在 R 中如何工作?【英文标题】:How does the `[<-` function work in R? 【发布时间】:2016-05-10 10:24:33 【问题描述】:

例如,我见过一些人使用 [&lt;- 作为带有波兰符号的函数

x <- matrix(1:4, nrow = 2)
`[<-`(x, 1, 2, 7)

返回

     [,1] [,2]
[1,]    1    7
[2,]    2    4

我已经尝试过使用 [&lt;- 一点,看起来像这样使用它会打印类似 x[1,2] &lt;- 7 的结果,而无需实际执行分配。但我无法确定这个函数实际上是做什么的,因为为?"[" 提供的文档只是顺便提及它,我无法在谷歌或 SO 中搜索“[

是的,我知道实际上使用这可能是一个可怕的想法,我只是为了更好地理解R而感到好奇。

【问题讨论】:

这更像是 R 将 x[1,2] &lt;- 7 转换为 x &lt;- '[&lt;-'(x, 1, 2, 7) 如果你了解[函数和&lt;-函数,那么[&lt;-函数就很有意义了。试试[(x,1,2)。试试&lt;-(a,1) 我没有看到这个重复。我认为的问题是为什么[&lt;- 实际上不会影响符号/命名对象x 中的子赋值。这似乎不是提名副本中提出的问题。 "[&lt;-" 是一个返回相应修改对象的函数。 "[&lt;-"(x, i, value) 似乎就是这样做的。要查看显式 "[&lt;-" 调用和 x[i] &lt;- value 的解析方式之间的区别,也许可以参见 '*tmp*' = "tmp"; x = 1:3; x[2] &lt;- 0; x; get("*tmp*") VS '*tmp*' = "tmp"; x = 1:3; "[&lt;-"(x, 2, 0); x; get("*tmp*"),如 here 所述。 【参考方案1】:

这是你需要做的事情才能坚持下去:

 `<-`(    `[`(   x, 1, 2), 7)  # or x <- `[<-`(   x, 1, 2, 7)
 x
     [,1] [,2]
[1,]    1    7
[2,]    2    4

基本上发生的事情是[ 正在创建指向x 的行列位置的指针,然后是&lt;-(这实际上是assign 的同义词,也可以在中缀表示法中使用)正在做实际的“永久”任务。不要被误导认为这是一个引用调用分配。我有理由确定仍然会创建一个临时值 x

您的版本确实进行了子分配(从它返回的内容可以看出),但该分配仅在调用 [&lt;- 的本地环境中,不包含全局环境。

【讨论】:

那么x[1,2]&lt;-7 是引用调用吗? 不。这也将创造一个临时价值。大多数“常规 R”分配是按承诺调用的,这更像是按值调用而不是按引用调用。 data.table 包对其对象进行了适当的修改。 R6 机制旨在提供对对象的更直接访问并防止复制开销。【参考方案2】:

由于`[`(x, y) 对对象进行切片,并且`&lt;-`(x, z) 执行赋值,因此`[&lt;-`(x,y,z) 似乎将执行赋值x[y] &lt;- y。 @42- 的回答很好地解释了 [&lt;- 的实际作用,而对 `levels<-`( What sorcery is this? 的最佳回答提供了一些关于 R 为何以这种方式工作的见解。

要查看 [&lt;- 的实际作用,您必须查看 C 源代码,[&lt;- 的源代码可以在 http://svn.r-project.org/R/trunk/src/main/subassign.c 找到(相关部分从第 1470 行开始)。您可以看到x,被“分配给”的对象受到保护,因此只有本地版本被变异。相反,我们使用 VectorAssign、MatrixAssign、ArrayAssign 等在本地执行赋值,然后返回结果。

【讨论】:

以上是关于`[<-` 函数在 R 中如何工作?的主要内容,如果未能解决你的问题,请参考以下文章

为啥不能在函数中使用“=” R 运算符?

如何在R中找到函数的上限和下限

了解如何在 R 中处理 .Internal C 函数

如何在某些R函数中隐式调用列

如何在 R 中使用“hclust”作为函数调用

如何在R中的sql查询中传递函数参数? [复制]