如何影响 R 中通过引用传递的对象?
How do I affect an object passed by reference in R?
我在 R 中使用 data.table
包。除其他外,data.table 导致 tables 通过引用传递。 Data.table 还支持通过 Ref 插入或删除列,所以你可以这样做...
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 中创建的,因此我不必 return 修改后的 table。容易生气。不幸的是,data.table 不支持插入或删除 行 byRef,所以会发生以下情况...
StripEvens<-function(DT){
DT <- DT[x %% 2 != 0]
}
StripEvens(DT)
DT
x x2
1: 1 1
2: 2 4
3: 3 9
<-
运算符按值工作,因此它在函数内部创建 DT 的副本。如果我不这样做,那么函数调用结束时 return DT 然后它是 'destroyed' 。如果我 do return DT 然后我可以找回看起来像我想要的方式的 table,但我已经通过制作副本完成了,这可能也路过Val.
问题来了。一旦 DT 被传递到我的函数 byRef 中,我如何让 R 继续在 DT byRef 上工作?同样,我如何让 R 将函数内部的 DT 视为对函数外部 DT 引用的同一对象的引用?这可能吗?
这会有点像 names(x) <- 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 语言编写函数,否则不可能通过引用进行实际修改。
我在 R 中使用 data.table
包。除其他外,data.table 导致 tables 通过引用传递。 Data.table 还支持通过 Ref 插入或删除列,所以你可以这样做...
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 中创建的,因此我不必 return 修改后的 table。容易生气。不幸的是,data.table 不支持插入或删除 行 byRef,所以会发生以下情况...
StripEvens<-function(DT){
DT <- DT[x %% 2 != 0]
}
StripEvens(DT)
DT
x x2
1: 1 1
2: 2 4
3: 3 9
<-
运算符按值工作,因此它在函数内部创建 DT 的副本。如果我不这样做,那么函数调用结束时 return DT 然后它是 'destroyed' 。如果我 do return DT 然后我可以找回看起来像我想要的方式的 table,但我已经通过制作副本完成了,这可能也路过Val.
问题来了。一旦 DT 被传递到我的函数 byRef 中,我如何让 R 继续在 DT byRef 上工作?同样,我如何让 R 将函数内部的 DT 视为对函数外部 DT 引用的同一对象的引用?这可能吗?
这会有点像 names(x) <- 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 语言编写函数,否则不可能通过引用进行实际修改。