Подтвердить что ты не робот

Обновление существующего файла Rdata

Я обнаружил, что мне нужно обновить один или два объекта данных в файле Rdata, который был создан ранее с помощью save. Если я не буду загружать файл, я могу забыть повторно сохранить некоторые объекты в файле. В качестве примера я работаю над пакетом с некоторыми объектами, хранящимися в sysdata.rda (справочные таблицы для внутреннего использования, которые я не хочу экспортировать), и хочу только беспокоиться об обновлении отдельных объектов.

Мне не удалось разобраться, если есть стандартный способ сделать это, поэтому создал свою собственную функцию.

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)
}

Однако это похоже на излишний. Есть ли лучший/более простой способ сделать это?

Как я уже сказал, правильно ли я предполагаю, что после вызова функции новая среда, созданная в рамках функции, будет уничтожена?

4b9b3361

Ответ 1

Вот немного более короткая версия:

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)
}

Я воспользовался тем, что функция load возвращает имя загруженных переменных, поэтому я могу использовать среду функций вместо ее создания. И при использовании get я старался только смотреть в среде, из которой вызывается функция, т.е. parent.frame().

Вот симуляция:

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

Ответ 2

Я добавил рефакторизованную версию ответа @flodel в пакете stackoverflow. Он использует среды явно, чтобы быть немного более защитными.

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)
}