Aktualizacja istniejącego pliku Rdata

Znalazłem się w sytuacji konieczności aktualizacji jednego lub dwóch obiektów danych w pliku Rdata utworzonym wcześniej za pomocą save. Jeśli nie będę uważać, aby załadować plik, mogę zapomnieć o ponownym zapisaniu niektórych obiektów w pliku. Jako przykład, pracuję nad pakietem z niektórymi obiektami przechowywanymi w sysdata.rda (tabele wyszukiwania do użytku wewnętrznego, których nie chcę eksportować) i chcę się martwić tylko o aktualizację poszczególnych obiektów.

Nie udało mi się ustalić, czy istnieje standardowy sposób na To stworzyło moją własną funkcję.
resave <- function (..., list = character(), file = stop("'file' must be specified")) {
  # create a staging environment to load the existing R objects
  stage <- new.env()
  load(file, envir=stage)
  # get the list of objects to be "resaved"
  names <- as.character(substitute(list(...)))[-1L]
  list <- c(list, names)
  # copy the objects to the staging environment
  lapply(list, function(obj) assign(obj, get(obj), stage))
  # save everything in the staging environment
  save(list=ls(stage, all.names=TRUE), file=file)
}
Wygląda to jednak na przesadę. Czy jest na to lepszy/łatwiejszy sposób?

Na marginesie, czy mam rację zakładając, że nowe środowisko stworzone w zakresie funkcji jest niszczone po wywołaniu funkcji?

 18
Author: zx8754, 2012-08-05

2 answers

Oto nieco krótsza wersja:

resave <- function(..., list = character(), file) {
   previous  <- load(file)
   var.names <- c(list, as.character(substitute(list(...)))[-1L])
   for (var in var.names) assign(var, get(var, envir = parent.frame()))
   save(list = unique(c(previous, var.names)), file = file)
}

Skorzystałem z faktu, że funkcja load zwraca nazwę załadowanych zmiennych, więc mogłem użyć środowiska funkcji zamiast tworzyć je. A przy użyciu get uważałem, aby szukać tylko w środowisku, z którego wywołana jest funkcja, tj. parent.frame().

Oto symulacja:

x1 <- 1
x2 <- 2
x3 <- 3
save(x1, x2, x3, file = "abc.RData")

x1 <- 10
x2 <- 20
x3 <- 30
resave(x1, x3, file = "abc.RData")

load("abc.RData")
x1
# [1] 10
x2
# [1] 2
x3
# [1] 30
 21
Author: flodel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-08-05 02:19:08

Dodałem refakturowaną wersję odpowiedzi @ flodel w pakiecie stackoverflow. Używa środowisk wyraźnie, aby być nieco bardziej defensywnym.

resave <- function(..., list = character(), file) {
  e <- new.env()
  load(file, e)
  list <- union(list, as.character(substitute((...)))[-1L])
  copyEnv(parent.frame(), e, list)
  save(list = ls(e, all.names=TRUE), envir = e, file = file)
}
 0
Author: Neal Fultz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-11-01 17:48:08