通过引用在 R 中的向量上进行子分配 [英] Sub-assign by reference on vector in R
问题描述
我能否以某种方式在原子向量上使用通过引用进行子分配?
当然不用将它包装在 1 列 data.table 中以使用 :=
.
Can I use sub-assign by reference on atomic vectors somehow?
Of course without wrapping it in 1 column data.table to use :=
.
library(data.table)
N <- 5e7
x <- sample(letters, N, TRUE)
X <- data.table(x = x)
upd_i <- sample(N, 1L, FALSE)
system.time(x[upd_i] <- NA_character_)
# user system elapsed
# 0.11 0.06 0.17
system.time(X[upd_i, x := NA_character_])
# user system elapsed
# 0.00 0.00 0.03
如果 R6 可以提供帮助,我愿意接受 R6 解决方案,因为它已经是我的部门之一.
我已经检查了 <-
里面的 R6
对象仍然复制:要点.
If R6 can help on that I'm open for R6 solution as it is one of my dep already.
I've already checked that <-
inside R6
object still makes copy: gist.
推荐答案
在最近的 R 版本(3.1-3.1.2+ 左右)中,对向量的赋值不会复制.但是,您不会通过运行 OP 的代码看到这一点,原因如下.因为您重用 x
并将其分配给其他对象,所以不会通知 R 在此时复制 x
,并且必须假设它不会被复制(在上面的特殊情况,我认为最好在 data.table::data.table
中更改它并通知 R 已制作副本,但这是一个单独的问题 - data.frame
遇到同样的问题),因此它在第一次使用时复制 x
.如果你稍微改变一下命令的顺序,你会发现没有区别:
In most recent R versions (3.1-3.1.2+ or so), assignment to a vector does not copy. You will not see that by running OP's code though, and the reason for that is the following. Because you reuse x
and assign it to some other object, R is not notified that x
is copied at that point, and has to assume that it won't be (in the particular case above, I think it'll be good to change it in data.table::data.table
and notify R that a copy has been made, but that's a separate issue - data.frame
suffers from same issue), and because of that it copies x
on first use. If you change the order of the commands a bit, you'd see no difference:
N <- 5e7
x <- sample(letters, N, TRUE)
upd_i <- sample(N, 1L, FALSE)
# no copy here:
system.time(x[upd_i] <- NA_character_)
# user system elapsed
# 0 0 0
X <- data.table(x = x)
system.time(X[upd_i, x := NA_character_])
# user system elapsed
# 0 0 0
# but now R will copy:
system.time(x[upd_i] <- NA_character_)
# user system elapsed
# 0.28 0.08 0.36
<小时>
(旧答案,主要留作好奇)
(old answer, mostly left as a curiosity)
您实际上可以使用 data.table
:=
运算符来修改您的向量(我认为您需要 R 版本 3.1+ 以避免在 列表
):
You actually can use the data.table
:=
operator to modify your vector in place (I think you need R version 3.1+ to avoid the copy in list
):
modify.vector = function (v, idx, value) setDT(list(v))[idx, V1 := value]
v = 1:5
address(v)
#[1] "000000002CC7AC48"
modify.vector(v, 4, 10)
v
#[1] 1 2 3 10 5
address(v)
#[1] "000000002CC7AC48"
这篇关于通过引用在 R 中的向量上进行子分配的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!