【问题标题】:How do I affect an object passed by reference in R?如何影响 R 中通过引用传递的对象?
【发布时间】:2015-04-02 17:49:09
【问题描述】:

我在 R 中使用 data.table 包。除其他外,data.table 会导致表通过引用传递。 Data.table 还支持通过引用插入或删除列,所以你可以做这样的事情......

library('data.table')

AddSquares<-function(DT){
  DT[,x2:=(x*x)]
}

DT<-data.table(x=1:3)
AddSquares(DT)

DT
   x x2
1: 1  1
2: 2  4
3: 3  9

x2 是在 DT byRef 中创建的,因此我不必返回修改后的表。容易小便。不幸的是,data.table 不支持插入或删除 rows byRef,所以会发生以下情况......

StripEvens<-function(DT){
  DT <- DT[x %% 2 != 0]
}

StripEvens(DT)

DT
   x x2
1: 1  1
2: 2  4
3: 3  9

&lt;- 运算符按值工作,因此它在函数内创建 DT 的副本。如果我不从该函数返回 DT,那么当函数调用结束时它会被“销毁”。如果我确实返回 DT,那么我可以取回一个看起来像我想要的方式的表格,但我已经通过制作一个副本来做到这一点,这也可能是传递 byVal。

所以问题来了。一旦 DT 被传递到我的函数 byRef 中,我如何让 R 继续在 DT byRef 上工作?等效地,如何使 R 将函数内部的 DT 视为对函数外部 DT 引用的同一对象的引用?这甚至可能吗?

【问题讨论】:

标签: r memory data.table pass-by-reference


【解决方案1】:

这会以与names(x) &lt;- letters 相同的方式做到这一点。也就是说,它看起来像是通过引用,但实际上并非如此。如果您关心语义而不是是否制作对象的副本,那么您可以执行以下操作:

library(data.table)
DT1 <- data.table(x=1:3)

StripEvens<-function(DT) {
  x <- substitute(DT)
  if(is.name(x)) {
    DT.ext <- get(as.character(x), parent.frame(), inherits=FALSE)
    if(identical(DT, DT.ext)) {
      assign(as.character(x), DT[x %% 2 != 0], envir=parent.frame())
  } } 
  return(invisible(NULL))
}

StripEvens(DT1)
DT1

生产:

   x
1: 1
2: 3

这不是完全健壮的(即如果对象实际上不在父框架中,则中断等),但可以通过一些工作使其健壮。更大的问题是对象实际上并没有通过引用来修改,而是被复制、修改和替换。正如其他人所指出的,除非您用 C 编写函数,否则不可能通过引用进行实际修改。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-09-11
    • 2012-02-03
    • 2019-06-05
    • 2011-07-06
    • 2012-07-07
    • 2012-01-05
    • 2012-07-16
    相关资源
    最近更新 更多