Wie kann ich ein Objekt in einen Variablennamen laden, den ich aus einer R-Datendatei angegeben habe?

97

Wenn Sie eine Variable in einer R-Datendatei mit speichern save, wird sie unter dem Namen gespeichert, den sie in der Sitzung hatte, in der sie gespeichert wurde. Wenn ich es später aus einer anderen Sitzung lade, wird es mit demselben Namen geladen, den das Ladeskript möglicherweise nicht kennen kann. Dieser Name könnte eine vorhandene gleichnamige Variable in der Ladesitzung überschreiben. Gibt es eine Möglichkeit, ein Objekt sicher aus einer Datendatei in einen angegebenen Variablennamen zu laden, ohne dass das Risiko besteht, dass vorhandene Variablen beschädigt werden?

Beispiel:

Speichersitzung:

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

Ladesitzung:

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

Wie ich möchte, dass es funktioniert:

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

Antworten:

93

Wenn Sie nur ein einzelnes Objekt .Rdataspeichern, verwenden Sie keine Datei, sondern eine .RDSDatei:

x <- 5
saveRDS(x, "x.rds")
y <- readRDS("x.rds")
all.equal(x, y)
Hadley
quelle
Aktualisiert, um zu berücksichtigen, dass diese in 2.13 nicht mehr experimentell sind.
Hadley
Bedeutet das, dass sie genau wie .Rdata-Dateien vollständig unterstützt werden?
Ryan C. Thompson
Da diese nicht mehr experimentell sind, markiere ich dies als akzeptierte Antwort. Das habe ich benutzt.
Ryan C. Thompson
Sie saveRDSund readRDS, entsprechend, speichern und alle Attribute des Objekts wiederherzustellen, darunter auch solche , die von einer Anwendung erstellt (via attr)? Ich habe versucht, diesen Ansatz anstelle von saveund zu verwenden load, um eine Problemumgehung für mein Problem zu finden. Es scheint jedoch nicht der Fall zu sein, es sei denn, ich mache etwas falsch: stackoverflow.com/questions/23701195/… .
Aleksandr Blekh
37

Ich benutze folgendes:

loadRData <- function(fileName){
#loads an RData file, and returns it
    load(fileName)
    get(ls()[ls() != "fileName"])
}
d <- loadRData("~/blah/ricardo.RData")
Ricardo
quelle
1
Dies ist eine großartige kleine Funktion. Hatte Probleme mit dem Versuch, Dinge zu laden (wollte sie nicht einfach in die globale Umgebung stellen, da ich weiß, dass dies zu Problemen führen würde.
Trevor Nederlof
4
So etwas gehört in die Basis R
Repmat
1
OH MEIN GOTT. Das ist fantastisch. Nur was ich brauche! #loveit
Sander W. van der Laan
Können Sie bitte die Logik der GET-Anweisung erweitern? Warum nicht mit FILENAME übereinstimmen, anstatt auszuschließen?
Nnachefski
35

Sie können eine neue Umgebung erstellen, die .rda-Datei in diese Umgebung laden und das Objekt von dort abrufen. Dies bringt jedoch einige Einschränkungen mit sich: Entweder wissen Sie, wie der ursprüngliche Name Ihres Objekts lautet, oder es ist nur ein Objekt in der Datei gespeichert.

Diese Funktion gibt ein Objekt zurück, das aus einer bereitgestellten .rda-Datei geladen wurde. Wenn die Datei mehr als ein Objekt enthält, wird ein beliebiges zurückgegeben.

load_obj <- function(f)
{
    env <- new.env()
    nm <- load(f, env)[1]
    env[[nm]]
}
Hong Ooi
quelle
3
Ist das new.envwirklich notwendig? Bietet der Funktionsaufruf selbst keine temporäre Umgebung?
Ryan C. Thompson
Sie können die gesamte Umgebung zurückgeben (return (env) oder return (environment ()), wenn Sie die Funktion gemäß dem Vorschlag von @Ryan ändern).
Wojciech Sobala
2
Wenn Sie die Funktionsumgebung verwenden, enthält sie f und hat ein übergeordnetes Element. Wahrscheinlich nicht das, was Sie wollen
Hadley
27

Sie könnten auch etwas ausprobieren wie:

# 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)
by0
quelle
4
Der Punkt ist, zu vermeiden, dass der Wert von x beim Laden überlastet wird.
Ryan C. Thompson
2

Falls jemand dies mit einer einfachen Quelldatei anstelle einer gespeicherten Rdata / RDS / Rda-Datei tun möchte, ist die Lösung der von @Hong Ooi bereitgestellten sehr ähnlich

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)

Drucke:

[1] "Wert von arg ist 7"

Und in der separaten Quelldatei TestSourceFile.R

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

Auch diese Lösung funktioniert nur, wenn genau eine Datei vorhanden ist. Wenn mehrere vorhanden sind, wird nur eine davon zurückgegeben (wahrscheinlich die erste, aber das ist nicht garantiert).

user2711915
quelle
1

Ich erweitere die Antwort von @ricardo, um die Auswahl einer bestimmten Variablen zu ermöglichen, wenn die .RdataDatei mehrere Variablen enthält (da meine Credits zum Bearbeiten einer Antwort niedrig sind). Nach dem Auflisten der in der .RdataDatei enthaltenen Variablen werden einige Zeilen zum Lesen von Benutzereingaben hinzugefügt .

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
quelle
1

Rdata-Datei mit einem Objekt

assign('newname', get(load('~/oldname.Rdata')))
Javier Acosta
quelle
1
Wird das Objekt nicht in den alten Namen geladen und dann auch dem neuen Namen zugewiesen? Das hilft nicht, wenn ich mir Sorgen über die Möglichkeit mache, eine vorhandene Variable zu überschreiben.
Ryan C. Thompson