我是否需要在函数内将 copy() 与 data.table 对象一起使用?
Do I need to use copy() with data.table objects inside a function?
我是否需要在函数内部使用 copy() 以避免对输入进行意外修改data.table?
例如
myfun <- function(mydata) {
mydata[,newcolumn := .N,by=id]
setnames(mydata, "newcolumn", "Count")
return(table(mydata$Count))
}
或
myfun <- function(mydata) {
temp <- copy(mydata)
temp[,newcolumn := .N,by=id]
setnames(temp, "newcolumn", "Count")
return(table(temp$Count))
}
或者将 data.table 传递给函数是否已经创建了一个副本,即使我使用 :=
赋值?
@Henrik 到 的链接答案确实解释了回答您问题的所有细节。
您的示例函数的这个(修改后的)版本 不 修改传递的 data.table
:
library(data.table)
dt <- data.table(id = 1:4, a = LETTERS[1:4])
myfun2 <- function(mydata) {
x <- mydata[, .(newcolumn = .N), by=id]
setnames(x, "newcolumn", "Count")
return(table(x$Count))
}
myfun2(dt)
这不会复制整个 data.table
(这会浪费 RAM 和 CPU 时间),只会将聚合结果写入一个新的 data.table
可以修改而没有副作用(=原始data.table
没有变化)。
> str(dt)
Classes ‘data.table’ and 'data.frame': 4 obs. of 2 variables:
$ id: int 1 2 3 4
$ a : chr "A" "B" "C" "D"
A data.table
总是通过对函数的引用传递,因此您必须小心不要修改它,除非您绝对确定要这样做。
data.table
包正是为这种高效的数据修改方式而设计的,无需通常的 "COW" ("copy on (first) write") 原则来支持高效的数据操作。
"Dangerous"修改adata.table
的操作主要有:
:=
赋值修改或新建列"in-place"
- 所有
set*
函数
如果您不想修改 data.table
,您可以仅使用行过滤器和列(选择)表达式(i
、j
、by
等参数)。
如果您在第二个(或更高版本的)链中修改 "by ref",链接也会阻止对原始 data.frame
的修改:
myfun3 <- function(mydata) {
# chaining also creates a copy
return(mydata[id < 3,][, a := "not overwritten outside"])
}
myfun3(dt)
# > str(dt)
# Classes ‘data.table’ and 'data.frame': 4 obs. of 3 variables:
# $ id: int 1 2 3 4
# $ a : chr "A" "B" "C" "D"
我是否需要在函数内部使用 copy() 以避免对输入进行意外修改data.table?
例如
myfun <- function(mydata) {
mydata[,newcolumn := .N,by=id]
setnames(mydata, "newcolumn", "Count")
return(table(mydata$Count))
}
或
myfun <- function(mydata) {
temp <- copy(mydata)
temp[,newcolumn := .N,by=id]
setnames(temp, "newcolumn", "Count")
return(table(temp$Count))
}
或者将 data.table 传递给函数是否已经创建了一个副本,即使我使用 :=
赋值?
@Henrik 到 的链接答案确实解释了回答您问题的所有细节。
您的示例函数的这个(修改后的)版本 不 修改传递的 data.table
:
library(data.table)
dt <- data.table(id = 1:4, a = LETTERS[1:4])
myfun2 <- function(mydata) {
x <- mydata[, .(newcolumn = .N), by=id]
setnames(x, "newcolumn", "Count")
return(table(x$Count))
}
myfun2(dt)
这不会复制整个 data.table
(这会浪费 RAM 和 CPU 时间),只会将聚合结果写入一个新的 data.table
可以修改而没有副作用(=原始data.table
没有变化)。
> str(dt)
Classes ‘data.table’ and 'data.frame': 4 obs. of 2 variables:
$ id: int 1 2 3 4
$ a : chr "A" "B" "C" "D"
A data.table
总是通过对函数的引用传递,因此您必须小心不要修改它,除非您绝对确定要这样做。
data.table
包正是为这种高效的数据修改方式而设计的,无需通常的 "COW" ("copy on (first) write") 原则来支持高效的数据操作。
"Dangerous"修改adata.table
的操作主要有:
:=
赋值修改或新建列"in-place"- 所有
set*
函数
如果您不想修改 data.table
,您可以仅使用行过滤器和列(选择)表达式(i
、j
、by
等参数)。
如果您在第二个(或更高版本的)链中修改 "by ref",链接也会阻止对原始 data.frame
的修改:
myfun3 <- function(mydata) {
# chaining also creates a copy
return(mydata[id < 3,][, a := "not overwritten outside"])
}
myfun3(dt)
# > str(dt)
# Classes ‘data.table’ and 'data.frame': 4 obs. of 3 variables:
# $ id: int 1 2 3 4
# $ a : chr "A" "B" "C" "D"