2017-09-05 5 views
0

本当に大きなJSONファイルをRにロードしようとしています。ファイルが大きすぎてマシンのメモリに収まらないので、jsonliteパッケージのstream_in/stream_out関数は本当に役に立ちます。これらの関数を使用して、データをロードせずにチャンク単位で最初にサブセット化し、サブセットデータを新しい小さなJSONファイルに書き込んでから、そのファイルをdata.frameとしてロードできます。しかし、この中間のJSONファイルは、stream_outと書かれている間に切り捨てられています(適切な場合)。今私は詳細を説明しようとします。あなたが見ることができるように、私は一時的に接続を開くR:jsonliteのstream_out関数が不完全な/切り捨てられたJSONファイルを生成する

con_out <- file(tmp <- tempfile(), open = "wb") 
stream_in(file("C:/User/myFile.json"), handler = function(df){ 
     df <- df[which(df$Var > 0), ] 
     stream_out(df, con_out, pagesize = 1000) 
    }, pagesize = 5000) 
myData <- stream_in(file(tmp)) 

が、私はこのように私のコードを書かれている(ドキュメントの例以下):私がしようとしています

私の元のJSONファイルstream_inを読んで、handlerの機能をデータの各チャンクのサブセットにして、それを接続に書き込んでください。

問題

私はエラーが表示されたときにmyData <- stream_in(file(tmp))、それを読もうとするまで、この手順は、何の問題もなく動作します。新しい一時的なJSONファイルを手動で開くと、一番下の行が常に不完全であることがわかります。次のようなものがあります。

{"Var1":"some data","Var2":3,"Var3":"some othe 

このファイルを最後に手動で削除してから、問題なくファイルを読み込む必要があります。

ソリューション私は徹底的に文書を読み、stream_out機能を見てみました

  1. を試してみた、と私は、この問題を引き起こす可能性のあるものを把握することはできません。私が持っている唯一の手がかりは、完了時にstream_out関数が自動的に接続を閉じるため、他のコンポーネントがまだ書いている間に接続を終了している可能性があります。

  2. Iは、中間data.frameの問題を除外するためにhandler関数内のすべてのチャンクでdata.frametail()端を印刷する印刷機能を挿入します。 data.frameはあらゆる間隔で完璧に生成されており、data.frameの最後の2〜3行がファイルに書き込まれている間に切り捨てられていることがわかります(書き込まれていません)。それは、全体がdata.framestream_outの後にrbindになっている)の最後が切れていることに注目してください。

  3. 非常に大きな数字、数字、およびInfを試してみるなど、pagesize引数で試してみました。何も働いていません。元のJSONファイルはストリーミングせずに読み取ることが大きすぎると、それは縮小さ(?)/ ndjson形式に実際にあるので

  4. 私はfromJSONようjsonliteの他の機能を使用することはできません。

私は、Windows 7のx64上でR 3.3.3のx64を実行しているシステム情報

。 6 GBのRAM、AMD Athlon II 4コア2.6 GHz

治療

不便などである、私はまだ手動でJSONファイルを開くと、それらを修正することにより、この問題に対処することができますが、それはいくつかのデータの損失につながるだし、私のスクリプトを自動化できるようにすることではないですプロジェクト全体を通して繰り返し実行する必要があります。

本当にありがとうございます。ありがとうございました。

+1

(〜トピック外ですが〜関連) Apache Drill-drill.apache.orgをチェックしてください。これはストリーミングJSON(ndjson)をうまく処理し、 'sergeant'パッケージを使用してdplyrを使用することができます。 – hrbrmstr

+0

ありがとう、hrbrmstr!私はそれをチェックし、成功すれば報告します。 –

答えて

0

私はこれがあなたの望む通りだと信じています。余分にstream_out/stream_inをする必要はありません。

myData <- new.env() 
stream_in(file("MOCK_DATA.json"), handler = function(df){ 
    idx <- as.character(length(myData) + 1) 
    myData[[idx]] <- df[which(df$id %% 2 == 0), ] ## change back to your filter 
}, pagesize = 200) ## change back to 1000 
myData <- myData %>% as.list() %>% bind_rows() 

(私はいくつかのMockarooでモックデータ作成:すべてが複数のチャンクで働いていたかどうかを確認するために生成された1000行、したがって、小さなページサイズを、私は使用されるフィルタものIDだった私が作成するために怠惰だったので。 Var列)

関連する問題