¿Cómo puedo cargar un objeto en un nombre de variable que especifico desde un archivo de datos R?

97

Cuando guarda una variable en un archivo de datos R usando save, se guarda con el nombre que tenía en la sesión que la guardó. Cuando luego voy a cargarlo desde otra sesión, se carga con el mismo nombre, que el script de carga no puede conocer. Este nombre podría sobrescribir una variable existente del mismo nombre en la sesión de carga. ¿Hay alguna manera de cargar de forma segura un objeto desde un archivo de datos en un nombre de variable especificado sin riesgo de golpear las variables existentes?

Ejemplo:

Guardar sesión:

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

Cargando sesión:

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

Cómo quiero que funcione:

x = 7
y = load_object_from_file("x.Rda")
print(x) # should print 7
print(y) # should print 5
Ryan C. Thompson
fuente

Respuestas:

93

Si solo está guardando un solo objeto, no use un .Rdataarchivo, use un .RDSarchivo:

x <- 5
saveRDS(x, "x.rds")
y <- readRDS("x.rds")
all.equal(x, y)
Hadley
fuente
Actualizado para reflejar que en 2.13 estos ya no son experimentales.
hadley
¿Eso significa que son totalmente compatibles, al igual que los archivos .Rdata?
Ryan C. Thompson
Dado que estos ya no son experimentales, lo estoy marcando como la respuesta aceptada. Esto es lo que he estado usando.
Ryan C. Thompson
¿ Guardar saveRDSy readRDS, en consecuencia, guardar y restaurar todos los atributos del objeto, incluidos los creados por una aplicación (vía attr)? Traté de usar este enfoque en lugar de savey load, tratando de encontrar una solución para mi problema. Sin embargo, no parece ser el caso, a menos que esté haciendo algo mal: stackoverflow.com/questions/23701195/… .
Aleksandr Blekh
37

Yo uso lo siguiente:

loadRData <- function(fileName){
#loads an RData file, and returns it
    load(fileName)
    get(ls()[ls() != "fileName"])
}
d <- loadRData("~/blah/ricardo.RData")
ricardo
fuente
1
Esta es una gran función. Estaba teniendo problemas al intentar cargar cosas (no quería simplemente ponerlas en el entorno global ya que sé que iba a tener problemas.
Trevor Nederlof
4
Algo como esto pertenece a la base R
Repmat
1
DIOS MIO. Esto es asombroso. ¡Justo lo que necesito! #loveit
Sander
¿Puede ampliar la lógica de la declaración GET? ¿Por qué no coincidir con FILENAME en lugar de excluir?
nnachefski
35

Puede crear un nuevo entorno, cargar el archivo .rda en ese entorno y recuperar el objeto desde allí. Sin embargo, esto impone algunas restricciones: o sabe cuál es el nombre original de su objeto o solo hay un objeto guardado en el archivo.

Esta función devuelve un objeto cargado desde un archivo .rda proporcionado. Si hay más de un objeto en el archivo, se devuelve uno arbitrario.

load_obj <- function(f)
{
    env <- new.env()
    nm <- load(f, env)[1]
    env[[nm]]
}
Hong Ooi
fuente
3
¿Es new.envrealmente necesario? ¿La llamada de función en sí misma no proporciona un entorno temporal?
Ryan C. Thompson
Puede devolver el entorno completo (return (env) o return (environment ()) cuando modifica la función de acuerdo con la sugerencia de @Ryan).
Wojciech Sobala
2
Si usa el entorno de función, contendrá f y tendrá un padre. Probablemente no sea lo que quieres
hadley
27

También puedes probar algo como:

# 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)
por0
fuente
4
El punto es evitar golpear el valor de x al cargar.
Ryan C. Thompson
2

En caso de que alguien esté buscando hacer esto con un archivo fuente simple, en lugar de un archivo Rdata / RDS / Rda guardado, la solución es muy similar a la proporcionada por @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)

Huellas dactilares:

[1] "El valor de arg es 7"

Y en el archivo fuente independiente TestSourceFile.R

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

Nuevamente, esta solución solo funciona si hay exactamente un archivo, si hay más, entonces solo devolverá uno de ellos (probablemente el primero, pero eso no está garantizado).

usuario2711915
fuente
1

Estoy ampliando la respuesta de @ricardo para permitir la selección de una variable específica si el .Rdataarchivo contiene varias variables (ya que mis créditos son bajos para editar una respuesta). Agrega algunas líneas para leer la entrada del usuario después de enumerar las variables contenidas en el .Rdataarchivo.

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

SeanM
fuente
1

Archivo Rdata con un objeto

assign('newname', get(load('~/oldname.Rdata')))
Javier Acosta
fuente
1
¿No cargará esto el objeto en el nombre anterior y luego también lo asignará al nuevo nombre también? Eso no ayudará si me preocupa la posibilidad de sobrescribir una variable existente.
Ryan C. Thompson