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

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)

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

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]]
}

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)

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


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


1

Plik Rdata z jednym obiektem

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

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
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.