2012-08-05 15 views
18

Ich habe festgestellt, dass ich ein oder zwei Datenobjekte in einer Rdata-Datei aktualisieren muss, die zuvor mit save erstellt wurde. Wenn ich nicht vorsichtig bin, die Datei zu laden, kann ich vergessen, einige Objekte in der Datei erneut zu speichern. Als Beispiel arbeite ich an einem Paket mit einigen Objekten, die in sysdata.rda gespeichert sind (Nachschlagetabellen für den internen Gebrauch, die ich nicht exportieren möchte) und möchte nur um das Aktualisieren einzelner Objekte kümmern.Aktualisieren einer vorhandenen Rdata-Datei

Ich habe es nicht geschafft, herauszufinden, ob es eine Standardmethode gibt, dies zu tun, also habe ich meine eigene Funktion erstellt.

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

Es scheint jedoch wie Overkill. Gibt es einen besseren/einfacheren Weg dies zu tun?

Nebenbei, bin ich richtig in der Annahme, dass eine neue Umgebung, die im Rahmen einer Funktion erstellt wird, nach dem Funktionsaufruf zerstört wird?

+0

Macht einen (oder zumindest mich :-)) wundern, warum 'save' keine" append "-Option hat. Ich werde r-help fragen und zurückkommen, wenn es eine nützliche Antwort gibt. –

+1

Ok, ich habe geschaut: https://stat.ethz.ch/pipermail/r-help/2006-March/101259.html gibt im Prinzip den gleichen Vorschlag wie die Antwort @flodel zur Verfügung gestellt. Persönlich würde ich gerne sehen, dass dies in der Basis "Speichern" -Funktion als "append = T" -Option gefaltet ist, aber es ist keine große Sache. –

+0

Ich habe 'as.character (substitute (liste (...))) [- 1L] '(Kopieren von' save') verwendet. Betrachtet man die Antwort der Mailing-Liste, wird "deparse" anstelle von "as.character" verwendet. Was sind die Vor-/Nachteile der beiden Ansätze? – seancarmody

Antwort

21

Hier ist eine etwas kürzere Version:

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

ich die Tatsache zunutze, nahm die load Funktion den Namen der geladenen Variablen gibt, so konnte ich die Funktion der Umgebung statt einer Erstellung verwenden. Und wenn get verwendet wurde, war ich vorsichtig, nur in der Umgebung zu suchen, von der die Funktion aufgerufen wird, d. H. parent.frame(). Hier

ist eine Simulation:

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 
+0

Danke! Eine Frage: Warum sind die Argumente 'liste' und' Datei' nicht in der Umgebung der Funktion? – seancarmody

+1

Sie sind in der Umgebung der Funktion, aber ich bin vorsichtig, sie nicht zu speichern: siehe, dass ich nur 'unique (c (vorherige, var.names))' speichern. – flodel

+0

Natürlich. Vielen Dank! Gute Antwort. – seancarmody

0

ich hinzugefügt habe eine Überarbeitete Version von @ flodel Antwort in dem Stackoverflow-Paket. Es verwendet Umgebungen explizit, um etwas defensiver zu sein.

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