在您的函数中,z 是对 x 的引用,直到 setDT。
library(data.table)
foo <- function(z) {print(address(z)); setDT(z); print(address(z))}
x <- data.frame(a = 1:2)
address(x)
#[1] "0x555ec9a471e8"
foo(x)
#[1] "0x555ec9a471e8"
#[1] "0x555ec9ede300"
在setDT 中,z 仍然指向与x 相同的地址:
setattr(z, "class", data.table:::.resetclass(z, "data.frame"))
setattr 不进行复制。所以x 和z 仍然指向同一个地址,并且现在都属于data.frame 类:
x <- data.frame(a = 1:2)
z <- x
class(x)
#[1] "data.frame"
address(x)
#[1] "0x555ec95de600"
address(z)
#[1] "0x555ec95de600"
setattr(z, "class", data.table:::.resetclass(z, "data.frame"))
class(x)
#[1] "data.table" "data.frame"
address(x)
#[1] "0x555ec95de600"
address(z)
#[1] "0x555ec95de600"
然后在这种情况下调用setalloccol:
assign("z", .Call(data.table:::Calloccolwrapper, z, 1024, FALSE))
现在让x 和z 指向不同的地址。
address(x)
#[1] "0x555ecaa09c00"
address(z)
#[1] "0x555ec95de600"
两者都有class data.frame
class(x)
#[1] "data.table" "data.frame"
class(z)
#[1] "data.table" "data.frame"
我想他们什么时候会使用
class(z) <- data.table:::.resetclass(z, "data.frame")
而不是
setattr(z, "class", data.table:::.resetclass(z, "data.frame"))
问题不会发生。
x <- data.frame(a = 1:2)
z <- x
address(x)
#[1] "0x555ec9cd2228"
class(z) <- data.table:::.resetclass(z, "data.frame")
class(x)
#[1] "data.frame"
class(z)
#[1] "data.table" "data.frame"
address(x)
#[1] "0x555ec9cd2228"
address(z)
#[1] "0x555ec9cd65a8"
但在class(z) <- value 之后z 不会指向它之前指向的相同地址:
z <- data.frame(a = 1:2)
address(z)
#[1] "0x5653dbe72b68"
address(z$a)
#[1] "0x5653db82e140"
class(z) <- c("data.table", "data.frame")
address(z)
#[1] "0x5653dbe82d98"
address(z$a)
#[1] "0x5653db82e140"
但在setDT 之后,它也不会指向它之前指向的相同地址:
z <- data.frame(a = 1:2)
address(z)
#[1] "0x55b6f04d0db8"
setDT(z)
address(z)
#[1] "0x55b6efe1e0e0"
正如@Matt-dowle 所指出的,也可以将x 中的数据更改为z:
x <- data.frame(a = c(1,3))
z <- x
setDT(z)
z[, b:=3:4]
z[2, a:=7]
z
# a b
#1: 1 3
#2: 7 4
x
# a
#1: 1
#2: 7
R.version.string
#[1] "R version 4.0.2 (2020-06-22)"
packageVersion("data.table")
#[1] ‘1.12.8’