Come posso caricare un oggetto in un nome di variabile specificato da un file di dati R?


97

Quando si salva una variabile in un file di dati R utilizzando save, viene salvata con il nome che aveva nella sessione che l'ha salvata. Quando in seguito vado a caricarlo da un'altra sessione, viene caricato con lo stesso nome, che lo script di caricamento non può conoscere. Questo nome potrebbe sovrascrivere una variabile esistente con lo stesso nome nella sessione di caricamento. C'è un modo per caricare in modo sicuro un oggetto da un file di dati in un nome di variabile specificato senza il rischio di distruggere le variabili esistenti?

Esempio:

Salvataggio della sessione:

x = 5
save(x, file="x.Rda")

Caricamento sessione:

x = 7
load("x.Rda")
print(x) # This will print 5. Oops.

Come voglio che funzioni:

x = 7
y = load_object_from_file("x.Rda")
print(x) # should print 7
print(y) # should print 5

Risposte:


93

Se stai salvando solo un singolo oggetto, non usare un .Rdatafile, usa un .RDSfile:

x <- 5
saveRDS(x, "x.rds")
y <- readRDS("x.rds")
all.equal(x, y)

Aggiornato per riflettere che nella 2.13 questi non sono più sperimentali.
Hadley

Ciò significa che sono completamente supportati, proprio come i file .Rdata?
Ryan C. Thompson

Poiché questi non sono più sperimentali, lo contrassegno come risposta accettata. Questo è quello che ho usato.
Ryan C. Thompson

Fare saveRDSe readRDS, di conseguenza, salvare e ripristinare tutti gli attributi dell'oggetto, inclusi quelli creati da un'applicazione (tramite attr)? Ho provato a utilizzare questo approccio al posto di savee load, cercando di trovare una soluzione alternativa per il mio problema. Tuttavia, non sembra essere il caso, a meno che non stia facendo qualcosa di sbagliato: stackoverflow.com/questions/23701195/… .
Aleksandr Blekh

37

Uso quanto segue:

loadRData <- function(fileName){
#loads an RData file, and returns it
    load(fileName)
    get(ls()[ls() != "fileName"])
}
d <- loadRData("~/blah/ricardo.RData")

1
Questa è una piccola grande funzione. Avevo problemi con il tentativo di caricare le cose in (non volevo semplicemente metterle nell'ambiente globale perché so che avrebbe avuto problemi.
Trevor Nederlof

4
Qualcosa del genere appartiene alla base R
Repmat

1
OH MIO DIO. Questo e spettacolare. Proprio quello che mi serve! #loveit
Sander W. van der Laan

Puoi espandere la logica dell'istruzione GET? Perché non abbinare a FILENAME invece di escludere?
nnachefski

35

È possibile creare un nuovo ambiente, caricare il file .rda in quell'ambiente e recuperare l'oggetto da lì. Tuttavia, questo impone alcune restrizioni: o sai qual è il nome originale per il tuo oggetto o c'è solo un oggetto salvato nel file.

Questa funzione restituisce un oggetto caricato da un file .rda fornito. Se nel file è presente più di un oggetto, ne viene restituito uno arbitrario.

load_obj <- function(f)
{
    env <- new.env()
    nm <- load(f, env)[1]
    env[[nm]]
}

3
È new.envdavvero necessario? La chiamata di funzione stessa non fornisce un ambiente temporaneo?
Ryan C. Thompson

Puoi restituire l'intero ambiente (return (env) o return (environment ()) quando modifichi la funzione secondo il suggerimento di @Ryan).
Wojciech Sobala

2
Se usi l'ambiente della funzione, conterrà f e avrà un genitore. Probabilmente non è quello che vuoi
Hadley

27

Potresti anche provare qualcosa come:

# Load the data, and store the name of the loaded object in x
x = load('data.Rsave')
# Get the object by its name
y = get(x)
# Remove the old object since you've stored it in y 
rm(x)

4
Il punto è evitare di rovinare il valore di x durante il caricamento.
Ryan C. Thompson

2

Nel caso qualcuno stia cercando di farlo con un semplice file sorgente, piuttosto che un file Rdata / RDS / Rda salvato, la soluzione è molto simile a quella fornita da @Hong Ooi

load_obj <- function(fileName) {

  local_env = new.env()
  source(file = fileName, local = local_env)

  return(local_env[[names(local_env)[1]]])

}

my_loaded_obj = load_obj(fileName = "TestSourceFile.R")

my_loaded_obj(7)

Stampe:

[1] "Il valore di arg è 7"

E nel file sorgente separato TestSourceFile.R

myTestFunction = function(arg) {
  print(paste0("Value of arg is ", arg))
}

Ancora una volta, questa soluzione funziona solo se c'è esattamente un file, se ce ne sono più, ne restituirà solo uno (probabilmente il primo, ma non è garantito).


1

Sto estendendo la risposta da @ricardo per consentire la selezione di una variabile specifica se il .Rdatafile contiene più variabili (poiché i miei crediti sono bassi per modificare una risposta). Aggiunge alcune righe per leggere l'input dell'utente dopo aver elencato le variabili contenute nel .Rdatafile.

loadRData <- function(fileName) {
  #loads an RData file, and returns it
  load(fileName)
  print(ls())
  n <- readline(prompt="Which variable to load? \n")
  get(ls()[as.integer(n)])
}

select_var <- loadRData('Multiple_variables.Rdata')


1

File Rdata con un oggetto

assign('newname', get(load('~/oldname.Rdata')))

1
Questo non caricherà l'oggetto nel vecchio nome e quindi lo assegnerà anche al nuovo nome? Ciò non aiuta se sono preoccupato per la possibilità di sovrascrivere una variabile esistente.
Ryan C. Thompson
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.