Jak mogę załadować obiekt do nazwy zmiennej, którą określam z pliku danych R?

97

Gdy zapisujesz zmienną w pliku danych R za pomocą save, jest ona zapisywana pod dowolną nazwą, jaką miała w sesji, w której została zapisana. Kiedy później idę załadować go z innej sesji, jest ładowany z tą samą nazwą, której skrypt ładujący prawdopodobnie nie może znać. Ta nazwa mogłaby zastąpić istniejącą zmienną o tej samej nazwie w sesji ładowania. Czy istnieje sposób na bezpieczne załadowanie obiektu z pliku danych do określonej nazwy zmiennej bez ryzyka przebicia istniejących zmiennych?

Przykład:

Zapisywanie sesji:

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

Sesja ładowania:

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

Jak chcę, żeby to działało:

x = 7
y = load_object_from_file("x.Rda")
print(x) # should print 7
print(y) # should print 5
Ryan C. Thompson
źródło

Odpowiedzi:

93

Jeśli zapisujesz tylko jeden obiekt, nie używaj .Rdatapliku, użyj .RDSpliku:

x <- 5
saveRDS(x, "x.rds")
y <- readRDS("x.rds")
all.equal(x, y)
hadley
źródło
Zaktualizowano, aby odzwierciedlić, że w 2.13 nie są one już eksperymentalne.
Hadley
Czy to oznacza, że ​​są w pełni obsługiwane, podobnie jak pliki .Rdata?
Ryan C. Thompson
Ponieważ nie są one już eksperymentalne, oznaczam to jako zaakceptowaną odpowiedź. To jest to, czego używałem.
Ryan C. Thompson
Czy saveRDSi readRDSodpowiednio zapisuje i przywraca wszystkie atrybuty obiektu, w tym te utworzone przez aplikację (przez attr)? Próbowałem zastosować to podejście zamiast savei load, próbując znaleźć obejście mojego problemu. Jednak wydaje się, że tak nie jest, chyba że robię coś źle: stackoverflow.com/questions/23701195/… .
Aleksandr Blekh
37

Używam następujących:

loadRData <- function(fileName){
#loads an RData file, and returns it
    load(fileName)
    get(ls()[ls() != "fileName"])
}
d <- loadRData("~/blah/ricardo.RData")
Ricardo
źródło
1
To świetna mała funkcja. Miałem problemy z próbą załadowania rzeczy (nie chciałem po prostu umieszczać ich w środowisku globalnym, ponieważ wiem, że będą problemy.
Trevor Nederlof
4
Coś takiego należy do bazy R
Repmat,
1
O MÓJ BOŻE. To jest niesamowite. Właśnie to czego potrzebuje! #loveit
Sander W. van der Laan
Czy możesz rozwinąć logikę wyciągu GET? Dlaczego nie dopasować do FILENAME zamiast wykluczać?
nnachefski
35

Możesz utworzyć nowe środowisko, załadować plik .rda do tego środowiska i pobrać stamtąd obiekt. Jednak nakłada to pewne ograniczenia: albo znasz oryginalną nazwę obiektu, albo w pliku zapisany jest tylko jeden obiekt.

Ta funkcja zwraca obiekt załadowany z dostarczonego pliku .rda. Jeśli w pliku jest więcej niż jeden obiekt, zwracany jest dowolny.

load_obj <- function(f)
{
    env <- new.env()
    nm <- load(f, env)[1]
    env[[nm]]
}
Hong Ooi
źródło
3
Czy to new.envnaprawdę konieczne? Czy samo wywołanie funkcji nie zapewnia tymczasowego środowiska?
Ryan C. Thompson,
Możesz zwrócić całe środowisko (return (env) lub return (environment ()), gdy zmodyfikujesz funkcję zgodnie z sugestią @Ryan).
Wojciech Sobala,
2
Jeśli używasz środowiska funkcji, będzie ono zawierało fi i będzie miało rodzica. Prawdopodobnie nie to, czego chcesz
Hadley
27

Możesz też spróbować czegoś takiego:

# 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
źródło
4
Chodzi o to, aby uniknąć wybicia wartości x podczas ładowania.
Ryan C. Thompson,
2

Jeśli ktoś chce to zrobić za pomocą zwykłego pliku źródłowego, a nie zapisanego pliku Rdata / RDS / Rda, rozwiązanie jest bardzo podobne do tego dostarczonego przez @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)

Wydruki:

[1] „Wartość argumentu to 7”

Oraz w osobnym pliku źródłowym TestSourceFile.R

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

Ponownie, to rozwiązanie działa tylko wtedy, gdy istnieje dokładnie jeden plik, jeśli jest ich więcej, zwróci tylko jeden z nich (prawdopodobnie pierwszy, ale nie jest to gwarantowane).

user2711915
źródło
1

Rozszerzam odpowiedź z @ricardo, aby umożliwić wybór określonej zmiennej, jeśli .Rdataplik zawiera wiele zmiennych (ponieważ moje kredyty są niskie, aby edytować odpowiedź). Dodaje kilka wierszy do odczytu danych wejściowych użytkownika po wyświetleniu zmiennych zawartych w .Rdatapliku.

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
źródło
1

Plik Rdata z jednym obiektem

assign('newname', get(load('~/oldname.Rdata')))
Javier Acosta
źródło
1
Czy to nie załaduje obiektu do starej nazwy, a następnie przypisze go również do nowej nazwy? To nie pomoże, jeśli martwię się możliwością nadpisania istniejącej zmiennej.
Ryan C. Thompson