2012-01-02 3 views
40

У меня есть Rdata файла, содержащие различные объекты:Получить конкретный объект из RDATA файл

New.Rdata 
    |_ Object 1 (e.g. data.frame) 
    |_ Object 2 (e.g. matrix) 
    |_... 
    |_ Object n 

Конечно, я могу загрузить кадр данных с load('New.Rdata'), однако, есть умный способ загрузить только один конкретный объект из этого файла и отказаться от других?

+1

В комментариях @DWin говорит, что нет. http://stackoverflow.com/questions/6550510/examining-contents-of-rdata-file-by-attaching-into-a-new-environment-possible –

+1

Но во всех вопросах-R я откладываю Симона. –

ответ

61

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

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

# convert .RData -> .rdb/.rdx 
e = local({load("New.RData"); environment()}) 
tools:::makeLazyLoadDB(e, "New") 

Загрузка БД затем загружает только индекс, но не содержимое. Содержимое загружаются как они используются:

lazyLoad("New") 
ls() 
x # if you had x in the New.RData it will be fetched now from New.rdb 

Так же, как с load() вы можете указать среду для загрузки в так что вам не нужно загрязнять глобальное рабочее пространство и т.д.

+1

Но поиск по-прежнему требует последовательного доступа через «New.RData», чтобы получить «x», правильно? Итак, если «x» находится в конце «New.RData», не может быть экономии времени? Question2: не будет ли память занята другими объектами, обнаруженными, поскольку процесс несериализации работает через «New.RData»? –

+1

Нет, поиск просто ищет в 'New.rdb' в начале' x' и загружает только 'x'. –

+8

Каковы шансы этих функций стать менее внутренними? – hadley

10

Вы можете использовать attach довольно чем load, который будет прикреплять объект данных к пути поиска, тогда вы можете скопировать один объект, который вас интересует, и отсоединить объект .Rdata.

Это все еще загружает все, но проще работать, чем загружать все в глобальную рабочую область (возможно, перезаписывать вещи, которые вы не хотите перезаписывать), а затем избавляться от всего, чего вы не хотите.

+3

Этот ответ хорош, но будет более полным с примером, потому что отсоединение объекта .RData от пути поиска не является интуитивным. Пример для извлечения 'someObj' из' someFile.RData': 'attach ('someFile.RData'); someObj <- someObj; detach ('file: someFile.RData') ' – C8H10N4O2

+0

@ C8H10N4O2, ваш пример хорош (и очень явный). Но если вы присоединяетесь к позиции по умолчанию (2) и не прикрепляете ничего еще до вызова detach, тогда работают по умолчанию, и вы можете просто вызвать 'detach()' без каких-либо аргументов и отделить файл. Это быстрее и проще; ваш подход безопаснее. –

4

Ответ Саймона Урбанека очень, очень приятный. Недостаток состоит в том, что он, кажется, не работает, если объект будет сохранен слишком велик:

tools:::makeLazyLoadDB(
    local({ 
    x <- 1:1e+09 
    cat("size:", object.size(x) ,"\n") 
    environment() 
    }), "lazytest") 
size: 4e+09 
Error: serialization is too large to store in a raw vector 

Я предполагаю, что это связано с ограничением текущей реализации R (у меня 2.15. 2), а не заканчивается из физической памяти и свопинга. Однако пакет saves может быть альтернативой для некоторых видов использования.

+1

Это скорее расширенный комментарий, чем ответ. – C8H10N4O2