Comment puis-je charger un objet dans un nom de variable que je spécifie à partir d'un fichier de données R?

97

Lorsque vous enregistrez une variable dans un fichier de données R en utilisant save, elle est enregistrée sous le nom qu'elle avait dans la session qui l'a enregistrée. Lorsque je vais plus tard le charger à partir d'une autre session, il est chargé avec le même nom, que le script de chargement ne peut pas connaître. Ce nom peut écraser une variable existante du même nom dans la session de chargement. Existe-t-il un moyen de charger en toute sécurité un objet à partir d'un fichier de données dans un nom de variable spécifié sans risque d'écraser les variables existantes?

Exemple:

Session de sauvegarde:

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

Session de chargement:

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

Comment je veux que ça marche:

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

Réponses:

93

Si vous ne sauvegardez qu'un seul objet, n'utilisez pas de .Rdatafichier, utilisez un .RDSfichier:

x <- 5
saveRDS(x, "x.rds")
y <- readRDS("x.rds")
all.equal(x, y)
hadley
la source
Mis à jour pour refléter que dans la version 2.13, ils ne sont plus expérimentaux.
hadley
Cela signifie-t-il qu'ils sont entièrement pris en charge, tout comme les fichiers .Rdata?
Ryan C. Thompson
Puisqu'elles ne sont plus expérimentales, je marque cela comme la réponse acceptée. C'est ce que j'utilise.
Ryan C. Thompson
Est-ce que saveRDSet readRDS, en conséquence, enregistrez et restaurez tous les attributs de l'objet, y compris ceux créés par une application (via attr)? J'ai essayé d'utiliser cette approche au lieu de saveet load, en essayant de trouver une solution de contournement à mon problème. Cependant, cela ne semble pas être le cas, sauf si je fais quelque chose de mal: stackoverflow.com/questions/23701195/… .
Aleksandr Blekh
38

J'utilise ce qui suit:

loadRData <- function(fileName){
#loads an RData file, and returns it
    load(fileName)
    get(ls()[ls() != "fileName"])
}
d <- loadRData("~/blah/ricardo.RData")
Ricardo
la source
1
C'est une super petite fonction. J'avais des problèmes en essayant de charger des choses (je ne voulais pas simplement les mettre dans l'environnement mondial car je sais que cela
poserait des
4
Quelque chose comme ça appartient à la base R
Repmat
1
OMG. C'est génial. Juste ce que j'ai besoin! #loveit
Sander
Pouvez-vous s'il vous plaît développer la logique de la déclaration GET? Pourquoi ne pas correspondre à FILENAME au lieu d'exclure?
nnachefski
35

Vous pouvez créer un nouvel environnement, charger le fichier .rda dans cet environnement et récupérer l'objet à partir de là. Cependant, cela impose certaines restrictions: soit vous connaissez le nom d'origine de votre objet, soit il n'y a qu'un seul objet enregistré dans le fichier.

Cette fonction renvoie un objet chargé à partir d'un fichier .rda fourni. S'il y a plus d'un objet dans le fichier, un arbitraire est renvoyé.

load_obj <- function(f)
{
    env <- new.env()
    nm <- load(f, env)[1]
    env[[nm]]
}
Hong Ooi
la source
3
Est-ce new.envvraiment nécessaire? L'appel de fonction lui-même ne fournit-il pas un environnement temporaire?
Ryan C. Thompson
Vous pouvez retourner l'environnement entier (return (env) ou return (environment ()) lorsque vous modifiez la fonction selon la suggestion @Ryan).
Wojciech Sobala
2
Si vous utilisez l'environnement de fonction, il contiendra f et aura un parent. Probablement pas ce que vous voulez
hadley
27

Vous pouvez également essayer quelque chose comme:

# 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)
par0
la source
4
Le but est d'éviter d'écraser la valeur de x lors du chargement.
Ryan C. Thompson
2

Au cas où quelqu'un chercherait à le faire avec un fichier source simple, plutôt qu'un fichier Rdata / RDS / Rda enregistré, la solution est très similaire à celle fournie par @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)

Impressions:

[1] "La valeur de arg est 7"

Et dans le fichier source séparé TestSourceFile.R

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

Encore une fois, cette solution ne fonctionne que s'il y a exactement un fichier, s'il y en a plus, elle n'en retournera que l'un (probablement le premier, mais ce n'est pas garanti).

utilisateur2711915
la source
1

J'étend la réponse de @ricardo pour permettre la sélection d'une variable spécifique si le .Rdatafichier contient plusieurs variables (car mes crédits sont faibles pour modifier une réponse). Il ajoute quelques lignes pour lire l'entrée utilisateur après avoir répertorié les variables contenues dans le .Rdatafichier.

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
la source
1

Fichier Rdata avec un objet

assign('newname', get(load('~/oldname.Rdata')))
Javier Acosta
la source
1
Cela ne chargera-t-il pas l'objet dans l'ancien nom et ne l'attribuera-t-il pas également au nouveau nom? Cela n'aidera pas si je m'inquiète de la possibilité d'écraser une variable existante.
Ryan C. Thompson