R(setnames
包)中的data.table
函数对于R来说是不常见的,因为它通过引用更改输入,这意味着它不会复制其运行的表。 (不要与setNames
包中的stats
混淆。
这会产生令人惊讶(且不方便)的后果:它会更改先前保存names
属性的任何对象。即:
require("data.table")
dt <- data.table(x = 1, y = 2)
dtnms <- function(dt){
nms <- names(dt)
print(nms)
setnames(dt, c("a", "b"))
nms
}
你会dtnms(dt)
返回什么? "x" "y"
当然。除非它没有 - setnames
也修改了函数中的nms
,因此在"x" "y"
之前打印setnames
时会返回"a" "b"
。如果您在stop()
之前放置setnames
,则可以看到nms
只是一个字符向量,没有特殊类别或其出处的其他指示。因此,我们希望setnames
不知道nms
来自何处,但不知何故链接是setnames
到“看”的链接。这怎么可能? (这与简单的数据框相同)。
进一步观察(记得每次重置dt
):
链接通过进一步的分配传播
dtnms2 <- function(dt){
nms <- names(dt)
print(nms)
nms2 <- nms
setnames(dt, c("a", "b"))
nms2
}
dtnms2(dt)
提供"a" "b"
该链接不仅仅是一个相似性问题
dtnms3 <- function(dt){
chv <- c("x", "y")
setnames(dt, c("a", "b"))
chv
}
dtnms3(dt)
提供"x" "y"
identical
dtnms4 <- function(dt){
chv <- c("x", "y")
nms <- names(dt)
identical(chv, nms)
}
dtnms4(dt)
提供TRUE
链接可以被破坏(这可能是解决此问题的最佳方式)
dtnms5 <- function(dt){
nms <- names(dt)
nms <- paste(nms)
setnames(dt, c("a", "b"))
nms
}
dtnms5(dt)
将"x" "y"
返回到预期值。 paste
打破了链接,无论它是什么。
所以我的问题是,链接是什么?为什么setnames
会更改nms
对象,这只是一个普通的旧字符向量,不知道它来自哪里?