2014-05-18 24 views
5

Do saveRDS e readRDS, corrispondentemente, salvare e ripristinare tutti gli attributi dell'oggetto, compresi quelli creati da un'applicazione (tramite attr)? Ho provato a utilizzare questo approccio invece di save e load, nel tentativo di trovare una soluzione alternativa per il mio problema collegato di seguito. Tuttavia, non sembra essere il caso, a meno che non stia facendo qualcosa di sbagliato: Can I access R data objects' attributes without fully loading objects from file?.Comportamento di saveRDS() e readRDS() in relazione agli attributi degli oggetti

risposta

10

Sì, lo fanno:

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 si basa fortemente su queste funzioni (così come le loro varianti). Ad esempio, vengono utilizzati per salvare l'area di lavoro dell'utente. Pertanto, sarebbe strano se non avessero memorizzato gli attributi.

Tuttavia, si noti che non è possibile memorizzare alcuni oggetti "creati dinamicamente" con questi. Questo include il file e connessioni SQL db gestori, SQL temporanei gestori di risultato, ecc Un esempio con le funzioni RCpp compilate:

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

Ora riavviare 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

Grazie mille! +1 e accetta la tua risposta. Beh, immagino, significa che il mio problema potrebbe essere altrove. Potrebbe essere in un modo che costruisco nomi, usando 'as.name'? O forse qualcos'altro? Gradirei, se guardassi la mia domanda originale, collegata sopra. –

+1

Assicurati che tutti gli oggetti che stai tentando di serializzare (archivia) non contengano puntatori alla memoria allocata dinamicamente (prova 'unlist (request)' or sth). Se lo fanno, dovrebbero essere convertiti in qualche modo in oggetti "puri R". – gagolews

+1

Apprezzo il tuo aggiornamento e commenta gli oggetti dinamici. Dziękuję! :-) –

3

saveRDS() fornisce una soluzione di gran lunga migliore al problema e al generale di salvataggio e caricamento di oggetti creati con R. saveRDS() serializza un oggetto R in un formato che può essere salvato. Wikipedia descrive questo così

... serializzazione è il processo di conversione di una struttura di dati o opporsi stato in un formato che può essere memorizzato (per esempio, in un buffer di memoria di file o , o trasmessa attraverso un collegamento di connessione di rete) e "resuscitato" più tardi nello stesso o in un altro ambiente informatico.

save() fa la stessa cosa, ma con una importante differenza: saveRDS() non salva sia l'oggetto e il suo nome è solo salva una rappresentazione dell'oggetto. Di conseguenza, l'oggetto salvato può essere caricato in un oggetto con nome all'interno di R che è diverso da dal nome che aveva quando originariamente serializzato.

Possiamo illustrare questo utilizzando il modello qui sotto

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

(Si noti che i due oggetti del modello hanno diversi ambienti all'interno delle loro rappresentazioni quindi dobbiamo ignorare questo quando si prova la loro identità.)

You' noteremo che nella chiamata a saveRDS() ho chiamato il file con estensione .rds. Questa sembra essere la convenzione utilizzata per l'oggetto serializzato di questo tipo; R usa spesso questa rappresentazione, ad esempio i meta-dati del pacchetto e i database utilizzati da help.search(). Al contrario l'estensione .rda viene spesso utilizzata per oggetti serializzati tramite save().

Quindi ce l'hai; saveRDS() e readRDS() sono le aggiunte più recenti al mio flusso di lavoro quotidiano.

Nota: saveRDS() non è una sostituzione drop-in per save(). La differenza principale è che save() può salvare molti oggetti in un file in una singola chiamata, mentre saveRDS(), essendo una funzione di livello inferiore, funziona con un singolo oggetto alla volta. Questa è una caratteristica per me dato il caso d'uso di cui sopra, ma se ti ritrovi a risparmiare ancora più di un paio di oggetti alla volta saveRDS() potrebbe non essere l'ideale per te. La seconda differenza significativa è che saveRDS() dimentica il nome originale dell'oggetto; nel caso d'uso sopra questo è anche visto come un vantaggio. Se il mantenimento del nome originale è importante per te , non c'è motivo di passare dall'uso di save() a saveRDS().

+0

Hai appena trovato la tua risposta. +1 e grazie - è una buona aggiunta alla risposta accettata. –