20

以前にを使用して作成されたRdataファイルの1つまたは2つのデータオブジェクトを更新する必要があることに気づきました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)
}

しかし、それはやり過ぎのようです。これを行うためのより良い/より簡単な方法はありますか?

余談ですが、関数のスコープ内に作成された新しい環境が関数呼び出しの後に破棄されると仮定するのは正しいですか?

4

2 に答える 2

26

これは少し短いバージョンです:

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
于 2012-08-05T01:51:54.633 に答える
0

スタックオーバーフローパッケージに@flodelの回答のリファクタリングバージョンを追加しました。環境を明示的に使用して、もう少し防御的にします。

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)
}
于 2015-11-01T17:48:08.110 に答える