Как я могу загрузить объект в имя переменной, указанное мной из файла данных R?

97

Когда вы сохраняете переменную в файле данных R с помощью save, она сохраняется под тем именем, которое у нее было в сеансе, в котором она была сохранена. Когда я позже загружаю его из другого сеанса, он загружается с тем же именем, которое сценарий загрузки не может знать. Это имя может перезаписать существующую переменную с тем же именем в сеансе загрузки. Есть ли способ безопасно загрузить объект из файла данных в указанное имя переменной без риска затирания существующих переменных?

Пример:

Сохранение сеанса:

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

Сеанс загрузки:

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

Как я хочу, чтобы это работало:

x = 7
y = load_object_from_file("x.Rda")
print(x) # should print 7
print(y) # should print 5
Райан С. Томпсон
источник

Ответы:

93

Если вы просто сохраняете один объект, не используйте .Rdataфайл, используйте .RDSфайл:

x <- 5
saveRDS(x, "x.rds")
y <- readRDS("x.rds")
all.equal(x, y)
Хэдли
источник
Обновлено, чтобы отразить, что в 2.13 они больше не являются экспериментальными.
Хадли
Означает ли это, что они полностью поддерживаются, как файлы .Rdata?
Райан С. Томпсон
Поскольку это больше не эксперимент, я отмечаю это как принятый ответ. Это то, что я использовал.
Райан С. Томпсон,
Сохранять saveRDSи readRDS, соответственно, сохранять и восстанавливать все атрибуты объекта, в том числе созданные приложением (через attr)? Я попытался использовать этот подход вместо saveи load, пытаясь найти способ решения моей проблемы. Однако, похоже, это не так, если я не делаю что-то не так: stackoverflow.com/questions/23701195/… .
Александр Блех
38

Я использую следующее:

loadRData <- function(fileName){
#loads an RData file, and returns it
    load(fileName)
    get(ls()[ls() != "fileName"])
}
d <- loadRData("~/blah/ricardo.RData")
Рикардо
источник
1
Это отличная маленькая функция. Были проблемы с попыткой загрузить вещи (не хотел просто помещать их в глобальную среду, поскольку я знаю, что это
приведет
4
Нечто подобное принадлежит базе R
Repmat
1
О, МОЙ БОГ. Это круто. Как раз то, что мне нужно! #loveit
Сандер В. ван дер Лаан
Не могли бы вы подробнее рассказать о логике оператора GET? Почему бы не сопоставить FILENAME вместо исключения?
nnachefski
35

Вы можете создать новую среду, загрузить в нее файл .rda и получить оттуда объект. Однако это накладывает некоторые ограничения: либо вы знаете исходное имя вашего объекта, либо в файле сохраняется только один объект.

Эта функция возвращает объект, загруженный из предоставленного файла .rda. Если в файле более одного объекта, возвращается произвольный.

load_obj <- function(f)
{
    env <- new.env()
    nm <- load(f, env)[1]
    env[[nm]]
}
Хонг Оои
источник
3
Действительно new.envли необходимо? Разве сам вызов функции не создает временную среду?
Райан С. Томпсон
Вы можете вернуть всю среду (return (env) или return (environment ()) при изменении функции в соответствии с предложением @Ryan).
Войцех Собала
2
Если вы используете функциональную среду, она будет содержать f и иметь родителя. Наверное, не то, что ты хочешь
Хэдли
27

Вы также можете попробовать что-то вроде:

# 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
источник
4
Дело в том, чтобы не сбивать значение x при загрузке.
Райан С. Томпсон
2

Если кто-то хочет сделать это с простым исходным файлом, а не с сохраненным файлом Rdata / RDS / Rda, решение очень похоже на то, что предоставлено @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)

Печать:

[1] «Значение аргумента 7»

И в отдельном исходном файле TestSourceFile.R

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

Опять же, это решение работает только в том случае, если есть ровно один файл, если их больше, то оно просто вернет один из них (возможно, первый, но это не гарантируется).

user2711915
источник
1

Я расширяю ответ от @ricardo, чтобы разрешить выбор конкретной переменной, если .Rdataфайл содержит несколько переменных (так как у меня мало кредитов для редактирования ответа). Он добавляет несколько строк для чтения пользовательского ввода после перечисления переменных, содержащихся в .Rdataфайле.

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

Rdata файл с одним объектом

assign('newname', get(load('~/oldname.Rdata')))
Хавьер Акоста
источник
1
Разве это не загрузит объект в старое имя, а затем также не назначит его новому имени? Это не поможет, если меня беспокоит возможность перезаписи существующей переменной.
Райан С. Томпсон