web-dev-qa-db-ja.com

Rdataファイルから特定のオブジェクトを取得する

さまざまなオブジェクトを含むRdataファイルがあります。

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

もちろん、load('New.Rdata')を使用してデータフレームをロードできますが、このファイルから特定のオブジェクトを1つだけロードし、他のオブジェクトを破棄するスマートな方法はありますか?

51
Seb

.RDataファイルにはインデックスがありません(コンテンツは1つの大きなペアリストとしてシリアル化されます)。ペアリストを調べて、好きなエントリだけを割り当てる方法をハックすることもできますが、Rレベルではそれができないため、簡単ではありません。

ただし、.RDataファイルを遅延読み込みデータベースに変換するだけで、各エントリを個別にシリアル化してインデックスを作成できます。いいのは、読み込みがオンデマンドになることです。

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

DBをロードすると、インデックスだけがロードされ、コンテンツはロードされません。コンテンツは使用時に読み込まれます。

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

load()と同様に、ロードする環境を指定できるため、グローバルワークスペースなどを汚染する必要がありません。

67
Simon Urbanek

データオブジェクトを検索パスにアタッチするattachではなくloadを使用して、目的の1つのオブジェクトをコピーし、.Rdataオブジェクトをデタッチすることができます。

これでもすべてが読み込まれますが、グローバルワークスペースにすべてを読み込んで(上書きしたくないものを上書きする可能性があります)、不要なものをすべて取り除くよりも操作が簡単です。

15
Greg Snow

サイモンアーバネックの答えは、非常に素晴らしいものです。欠点は、保存するオブジェクトが大きすぎると機能しないように見えることです。

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 パッケージは、一部の用途では代替手段になる場合があります。

4
Mars