2016-09-28 16 views
7

JSONデータを適切なデータフレームに正しく変換する方法がわかりません。私はトラックがたくさんあると私は、データセットは次のようになりたいのですが複雑なJSONデータを単一のデータフレームに変換するにはどうすればよいですか?

{ 
"data":[ 
{"track":[ 
{"time":"2015","midpoint":{"x":6,"y":8},"realworld":{"x":1,"y":3},"coordinate":{"x":16,"y":38}}, 
{"time":"2015","midpoint":{"x":6,"y":8},"realworld":{"x":1,"y":3},"coordinate":{"x":16,"y":37}}, 
{"time":"2016","midpoint":{"x":6,"y":9},"realworld":{"x":2,"y":3},"coordinate":{"x":16,"y":38}} 
]}, 
{"track":[ 
{"time":"2015","midpoint":{"x":5,"y":9},"realworld":{"x":-1,"y":3},"coordinate":{"x":16,"y":38}}, 
{"time":"2015","midpoint":{"x":5,"y":9},"realworld":{"x":-1,"y":3},"coordinate":{"x":16,"y":38}}, 
{"time":"2016","midpoint":{"x":5,"y":9},"realworld":{"x":-1,"y":3},"coordinate":{"x":16,"y":38}}, 
{"time":"2015","midpoint":{"x":3,"y":15},"realworld":{"x":-9,"y":2},"coordinate":{"x":17,"y":38}} 
]}, 
{"track":[ 
{"time":"2015","midpoint":{"x":6,"y":7},"realworld":{"x":-2,"y":3},"coordinate":{"x":16,"y":39}} 
]}]} 

track time midpoint realworld coordinate 
1 
1 
1 
2 
2 
2 
2 
3 

これまでのところ、私はこれを持っているこれは、いくつかの例私のデータの構造を示したデータであります:

json_file <- "testdata.json" 
data <- fromJSON(json_file) 
data2 <- list.stack(data, fill=TRUE) 

は今のところ、それは次のように出てくる:

data output

これを適切な形式で入手するにはどうすればよいですか?

答えて

4

fromJSONと読むときにflatten = TRUEパラメータを追加します。これにより、ネストされたリストが3つのデータフレームのリストに表示されます。使い方:

library(jsonlite) 
# read the json 
jsondata <- fromJSON(txt, flatten = TRUE) 

# bind the dataframes in the nested 'track' list together  
dat <- do.call(rbind, jsondata$data$track) 

# add a track variable 
dat$track <- rep(1:length(jsondata$data$track), sapply(jsondata$data$track, nrow)) 

ができます:

> dat 
    time midpoint.x midpoint.y realworld.x realworld.y coordinate.x coordinate.y track 
1 2015   6   8   1   3   16   38  1 
2 2015   6   8   1   3   16   37  1 
3 2016   6   9   2   3   16   38  1 
4 2015   5   9   -1   3   16   38  2 
5 2015   5   9   -1   3   16   38  2 
6 2016   5   9   -1   3   16   38  2 
7 2015   3   15   -9   2   17   38  2 
8 2015   6   7   -2   3   16   39  3 

別の、短い、アプローチはdata.tableパッケージからrbindlistと組み合わせてjsonliteを使用している:

library(jsonlite) 
library(data.table) 
# read the json 
jsondata <- fromJSON(txt, flatten = TRUE) 
# bind the dataframes in the nested 'track' list together 
# and include an id-column at the same time 
dat <- rbindlist(jsondata$data$track, idcol = 'track') 

またはdplyrパッケージからbind_rowsのあります同様の方法:

library(dplyr) 
dat <- bind_rows(jsondata$data$track, .id = 'track') 

使用するデータ:stream_inがndjsonのためであり、あなたがndjsonを持っていないので、

txt <- '{ 
"data":[ 
{"track":[ 
{"time":"2015","midpoint":{"x":6,"y":8},"realworld":{"x":1,"y":3},"coordinate":{"x":16,"y":38}}, 
{"time":"2015","midpoint":{"x":6,"y":8},"realworld":{"x":1,"y":3},"coordinate":{"x":16,"y":37}}, 
{"time":"2016","midpoint":{"x":6,"y":9},"realworld":{"x":2,"y":3},"coordinate":{"x":16,"y":38}} 
]}, 
{"track":[ 
{"time":"2015","midpoint":{"x":5,"y":9},"realworld":{"x":-1,"y":3},"coordinate":{"x":16,"y":38}}, 
{"time":"2015","midpoint":{"x":5,"y":9},"realworld":{"x":-1,"y":3},"coordinate":{"x":16,"y":38}}, 
{"time":"2016","midpoint":{"x":5,"y":9},"realworld":{"x":-1,"y":3},"coordinate":{"x":16,"y":38}}, 
{"time":"2015","midpoint":{"x":3,"y":15},"realworld":{"x":-9,"y":2},"coordinate":{"x":17,"y":38}} 
]}, 
{"track":[ 
{"time":"2015","midpoint":{"x":6,"y":7},"realworld":{"x":-2,"y":3},"coordinate":{"x":16,"y":39}} 
]}]}' 
+1

はIMO最終的な解決にあなたの反復で残してスーパー有益だっただろうが、最終的な結果は++エレガントです。 – hrbrmstr

+0

@hrbrmstr thx :-)しかし、「最終的な解決策にあなたの反復を残す」*とはどういう意味ですか? – Jaap

+0

ああ、そうです。私は最終版を誤って読んで、あなたがサプリーを取り去ったと思っていました(ちょうど異なるフォーマットでした)。私は今、なぜ 'dlyr :: bind_rows()'を本当に呼び出す '' purrr :: flatten_df() ''がこれでうまくいかないのかを考えようとしています。私もいくつかの '' purrr'コールでRをセグメンテーションすることができたので、これはOP全体(GHの問題を提出する必要がある)の良いポストでした。 – hrbrmstr

2

サヒールの答え(それはすでに削除されていない場合は)誤解を招くおそれがあります。入れ子にされたリストをちょっと手間をかけるだけです。

library(jsonlite) 
library(purrr) 
library(readr) 

dat <- fromJSON(txt, simplifyVector=FALSE) # read in your JSON 
map(dat$data, "track") %>%     # move past the top-level "data" element and iterate over the "track"s 
    map_df(function(track) {     # iterate over each element of "track" 
    map_df(track, ~as.list(unlist(track))) # convert it to a data frame 
    }, .id="track") %>%      # add in the track "id" 
    type_convert()       # convert mangled types 
## # A tibble: 8 × 8 
## track time midpoint.x midpoint.y realworld.x realworld.y coordinate.x coordinate.y 
## <int> <int>  <int>  <int>  <int>  <int>  <int>  <int> 
## 1  1 2016   6   9   2   3   16   38 
## 2  1 2016   6   9   2   3   16   38 
## 3  1 2016   6   9   2   3   16   38 
## 4  2 2015   3   15   -9   2   17   38 
## 5  2 2015   3   15   -9   2   17   38 
## 6  2 2015   3   15   -9   2   17   38 
## 7  2 2015   3   15   -9   2   17   38 
## 8  3 2015   6   7   -2   3   16   39 

これもまとも列型であなたを残し、あなたがオンにreadr::type_convertcol_typesパラメータを使用したいかもしれません:私は次のようにも小さくすることができるが、それは速い、直接攻撃ハックだったと思いますtimeを文字ベクトルに変換します。

代わり:

library(jsonlite) 
library(purrr) 
library(tibble) 

dat <- fromJSON(txt, flatten=TRUE) # read in your JSON 
map_df(dat$data$track, as_tibble, .id="track") 
関連する問題