Удалить весь data.table по ссылке - PullRequest
0 голосов
/ 24 октября 2018

Можно ли удалить объект 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()

Это проясняет ситуацию?Прошу прощения, что не прояснил с самого начала.

Ответы [ 2 ]

0 голосов
/ 25 октября 2018

Это должно сработать:

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")
0 голосов
/ 24 октября 2018

Это должно работать:

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
...