是否可以通过引用删除data.table
对象?如何实现一个函数rm_tbl()
,该函数需要一个data.table
对象并将NULL
分配给在任何环境(这是globalenv的后代)中指向该对象的任何名称?
示例,由于明显的原因,这些示例不起作用,但是可能传达了我要实现的目标的想法:
rm_tbl_1 <- function(tbl) {
rm(tbl)
invisible(NULL)
}
rm_tbl_2 <- function(tbl) {
tbl <<- NULL
invisible(NULL)
}
以下内容很接近,但是有点骇人听闻(也不会导致NULL
而是零行data.table
)
rm_tbl_3 <- function(tbl) {
tbl[, colnames(tbl) := rep(list(NULL), ncol(tbl))]
invisible(NULL)
}
出于完整性考虑:
dt <- data.table(a = 1:3, b = 2:4)
rm_tbl_1(dt)
dt
rm_tbl_2(dt)
dt
rm_tbl_3(dt)
dt
根据@Gregor的建议,进一步解释:我面临的问题是我有一个很大的data.table
。现在在函数中的某处,我对该对象做一些事情,例如致电data.table::split()
,我不再需要原始的data.table
。此外,为了对数据进行进一步的转换,我需要将原始data.table
的内存退回。我该怎么办?
一个例子:
fun_a <- function() {
dt <- data.table(a = 1:2, b = 2:3)
fun_b(dt)
}
fun_b <- function(tbl) {
temp <- split(tbl, by = "b")
rm_dt(tbl)
do_stuff_with_dt(temp)
}
fun_a()
这可以清除一切吗?对不起,我一开始不清楚。
答案 0 :(得分:2)
这应该可以解决问题:
rm_dt <- function(name) {
# Get data.table of all data.tables in global environment
tbls <- tables(env=.GlobalEnv, silent=TRUE)
# Look up the externalptr address for each data.table
tbls <- tbls[, .(addr=eval(parse(text=sprintf("data.table::address(%s)", NAME)))),
by = NAME]
# Find all data.tables that have the same externalptr address as the one requested for deletion
to_rm <- tbls[addr == tbls[NAME == name, addr], NAME]
# Delete them
rm(list=to_rm, pos=".GlobalEnv")
}
dt <- data.table(a=1)
dt2 <- dt
dt3 <- data.table(a=1)
rm_dt("dt") # should delete dt and dt2, but not dt3
请注意,这只会删除全局环境中的所有引用,如果您在另一个环境中创建了引用,则不会将其删除:
dt <- data.table(a=1)
dt2 <- dt
e <- new.env()
e$dt3 <- dt
# dt and dt2 will be removed, but e$dt3 will still exist
rm_dt("dt")
答案 1 :(得分:0)
这应该有效:
rm_tbl_4 <- function(tbl) {
tbl = deparse(substitute(tbl))
rm(list = tbl, pos = ".GlobalEnv")
}
dt <- data.table(a = 1:3, b = 2:4)
rm_tbl_4(dt)
dt
您还可以将环境作为函数变量包括在内,以便您决定从何处删除它。
rm_tbl_4 <- function(tbl, env) {
tbl = deparse(substitute(tbl))
rm(list = tbl, pos = env)
}
dt <- data.table(a = 1:3, b = 2:4)
rm_tbl_4(dt, env=".GlobalEnv")
dt