2014-05-18 3 views
5

Do saveRDS und readRDS, entsprechend speichern und wiederherstellen alle Attribute des Objekts, einschließlich der von einer Anwendung (über attr) erstellt Attribute? Ich habe versucht, diesen Ansatz anstelle von save und load zu verwenden, um eine Problemumgehung für mein unten verknüpftes Problem zu finden. Es scheint jedoch nicht der Fall zu sein, es sei denn, ich mache etwas falsches: Can I access R data objects' attributes without fully loading objects from file?.Verhalten von saveRDS() und readRDS() in Bezug auf die Attribute der Objekte

Antwort

10

Ja, sie tun:

test <- structure(1:10, names=LETTERS[1:10], color='red', xxx='yyy') 
attr(test, which='uuu') <- 'zzz' 
test 
## A B C D E F G H I J 
## 1 2 3 4 5 6 7 8 9 10 
## attr(,"color") 
## [1] "red" 
## attr(,"xxx") 
## [1] "yyy" 
## attr(,"uuu") 
## [1] "zzz" 
saveRDS(test, '/tmp/test.rds') 
test2 <- readRDS('/tmp/test.rds') 
identical(test, test2) 
## [1] TRUE 

R stützt sich stark auf diese Funktionen (sowie deren Varianten). Zum Beispiel werden sie verwendet, um den Arbeitsbereich des Benutzers zu speichern. Daher wäre es seltsam, wenn sie die Attribute nicht gespeichert hätten.

Beachten Sie jedoch, dass Sie einige "dynamisch erstellte" Objekte mit diesen nicht speichern können. Dazu gehören Datei- und SQL DB-Verbindungen Handler, temporäre SQL Ergebnis Handler usw. Ein Beispiel mit RCPP kompilierten Funktionen:

library('Rcpp') 
library('inline') 
cppFunction("int one() { return 1; }") 
one() # it works 
## [1] 1 
one # contains a pointer to dynamically allocated mem chunk 
## function() 
## .Primitive(".Call")(<pointer: 0x7f52c33a7680>) 
saveRDS(one, '/tmp/one.rds') 

Jetzt starten wir R ...

one <- readRDS('/tmp/one.rds') 
one # the pointer is no longer valid 
## function() 
## .Primitive(".Call")(<pointer: (nil)>) 
one() # doesn't work 
## Error in .Primitive(".Call")(<pointer: (nil)>) : 
## NULL value passed as symbol address 
+0

Vielen Dank! +1 und akzeptiere deine Antwort. Nun, ich denke, es bedeutet, dass mein Problem woanders sein könnte. Könnte es so sein, dass ich Namen konstruiere, indem ich 'as.name' verwende? Oder vielleicht noch etwas? Ich würde mich freuen, wenn Sie sich meine oben verlinkte Frage ansehen würden. –

+1

Stellen Sie sicher, dass alle Objekte, die Sie serialisieren (speichern), keine Zeiger auf dynamisch zugewiesenen Speicher enthalten (versuchen Sie 'unlist (request)' oder etw). Wenn sie das tun, sollten sie irgendwie in "reine R" -Objekte umgewandelt werden. – gagolews

+1

Schätzen Sie Ihr Update und kommentieren Sie dynamische Objekte. Dziękuję! :-) –

3

saveRDS() eine weit bessere Lösung bietet auf das Problem und auf das allgemeine Speichern und Laden von Objekten, die mit R erstellt wurden. serialisiert ein R-Objekt in ein Format, das gespeichert werden kann. Wikipedia beschreibt dies so

... Serialisierung ist der Prozess eine Datenstruktur des Umwandelns oder Zustand in ein Format-Objekt, das (beispielsweise gespeichert werden kann, in einer Datei oder Speicherpuffer, oder über eine Netzwerkverbindung Verbindung übertragen) und "später wiederbelebt" in der gleichen oder einer anderen Computerumgebung.

save() macht das Gleiche, aber mit einem wichtigen Unterschied: saveRDS() speichert nicht sowohl das Objekt und seinen Namen es speichert nur eine Darstellung des Objekts. Als Ergebnis kann das gespeicherte Objekt in ein benanntes Objekt innerhalb von R geladen werden, das sich von dem Namen, den es ursprünglich serialisiert hatte, unter unterscheidet.

Wir können zeigen dies das unten Modell

ls() [1] "mod" 
saveRDS(mod, "mymodel.rds") 
mod2 <- readRDS("mymodel.rds") 
ls() [1] "mod" "mod2" 
identical(mod, mod2, ignore.environment = TRUE) [1] TRUE 

(Beachten Sie, dass die beiden Modellobjekte unterschiedliche Umgebungen in ihren Vorstellungen haben, so dass wir dies ignorieren, wenn ihre Identität zu prüfen.)

Sie‘ Ich werde feststellen, dass ich im Aufruf an saveRDS() die Datei mit der Erweiterung .RDS benannt habe. Dies scheint die Konvention zu sein, die für serialisierte Objekte dieser Art verwendet wird; R verwendet diese Repräsentation häufig, zum Beispiel Paket-Metadaten und die von help.search() verwendeten Datenbanken. Im Gegensatz dazu wird die Erweiterung .RDA oft für Objekte verwendet, die über save() serialisiert werden.

So haben Sie es; saveRDS() und readRDS() sind die neuesten Ergänzungen zu meinem täglichen Workflow.

Hinweis: saveRDS() ist kein Drop-in-Ersatz für save(). Der Hauptunterschied besteht darin, dass save() viele Objekte in einer Datei in einem einzigen Aufruf speichern kann, , während saveRDS(), als eine untergeordnete Funktion, mit einem einzelnen Objekt zu einem Zeitpunkt arbeitet. Dies ist eine Funktion für mich angesichts der oben genannten Anwendungsfall, aber wenn Sie wieder mehr als ein paar Objekte auf einmal speichern finden saveRDS() möglicherweise nicht ideal für Sie. Der zweite signifikante Unterschied ist, dass saveRDS() den ursprünglichen Namen des Objekts vergisst; im obigen Anwendungsfall wird ebenfalls als Vorteil gesehen. Wenn es wichtig ist, den ursprünglichen Namen zu erhalten, dann gibt es keinen Grund, von der Verwendung save() zu saveRDS() zu wechseln.

+0

Gerade lief über Ihre Antwort. +1 und danke - es ist eine gute Ergänzung zu der angenommenen Antwort. –

Verwandte Themen