2017-04-06 6 views
1

Ich habe den folgenden Code, der Daten aus einer JSON-Datei extrahiert."embedded" data.frame aus JSON

library(jsonlite) 

file_path <- 'C:/some/file/path.json' 

df <- jsonlite::fromJSON(txt = file_path , 
         simplifyVector = FALSE, 
         simplifyDataFrame = TRUE, 
         simplifyMatrix = FALSE, 
         flatten = FALSE) 

Die Datenstruktur ist sehr verschachtelt. Mein Ansatz extrahiert 99% davon ganz gut, aber in einem bestimmten Teil der Daten, die ich stieß auf ein Phänomen, das ich als „embedded“ Datenrahmen beschreiben würde:

df <- structure(
    list(
    ID = c(1L, 2L, 3L, 4L, 5L), 
    var1 = c('a', 'b', 'c', 'd', 'e'), 
    var2 = structure(
     list(
     var2a = c('v', 'w', 'x', 'y', 'z'), 
     var2b = c('vv', 'ww', 'xx', 'yy', 'zz')), 
     .Names = c('var2a', 'var2b'), 
     row.names = c(NA, 5L), 
     class = 'data.frame'), 
    var3 = c('aa', 'bb', 'cc', 'dd', 'ee')), 
    .Names = c('ID', 'var1', 'var2', 'var3'), 
    row.names = c(NA, 5L), 
    class = 'data.frame') 

# Looks like this: 
# ID var1 var2.var2a var2.var2b var3 
# 1 1 a   v   vv aa 
# 2 2 b   w   ww bb 
# 3 3 c   x   xx cc 
# 4 4 d   y   yy dd 
# 5 5 e   z   zz ee 

Diese sieht wie ein normalen Daten Rahmen, und es verhält sich größtenteils so. statt nur einem einfachen data.frame

class(df) 
# [1] "data.frame" 

df[1,] 
# ID var1 var2.var2a var2.var2b var3 
# 1  a   v   vv aa 

dim(df) 
# [1] 5 4 
# One less than expected due to embedded data frame 

lapply(df, class) 
# $ID 
# [1] "integer" 
# 
# $var1 
# [1] "character" 
# 
# $var2 
# [1] "data.frame" 
# 
# $var3 
# [1] "character" 

str(df) 
# 'data.frame': 5 obs. of 4 variables: 
# $ ID : int 1 2 3 4 5 
# $ var1: chr "a" "b" "c" "d" ... 
# $ var2:'data.frame': 5 obs. of 2 variables: 
# ..$ var2a: chr "v" "w" "x" "y" ... 
# ..$ var2b: chr "vv" "ww" "xx" "yy" ... 
# $ var3: chr "aa" "bb" "cc" "dd" ... 

Was hier los ist, warum jsonlite ist diese seltsame Struktur zu schaffen? Kann ich dieses Verhalten vermeiden, und wenn nicht, wie kann ich das am elegantesten korrigieren? Ich habe den Ansatz unten verwendet, aber es fühlt sich im besten Fall sehr hacky an.

# Any columns with embedded data frame? 
newX <- X[,-which(lapply(X, class) == 'data.frame')] %>% 
    # Append them to the end 
    cbind(X[,which(lapply(X, class) == 'data.frame')]) 

aktualisieren

Die vorgeschlagene Abhilfe mein Problem löst, aber ich fühle mich immer noch wie ich das seltsame eingebettet data.frame Struktur nicht verstehen. Ich hätte gedacht, dass eine solche Struktur durch R-Datenformat-Konventionen illegal wäre oder sich zumindest hinsichtlich der Teilmenge unter Verwendung von [ anders verhält. Ich habe dazu eine geöffnet.

Antwort

1

Ich glaube, Sie wollen Ihr df Objekt glätten:

json <- toJSON(df) 
flat_df <- fromJSON(json, flatten = T) 

str(flat_df) 

'data.frame': 5 obs. of 5 variables: 
$ ID  : int 1 2 3 4 5 
$ var1  : chr "a" "b" "c" "d" ... 
$ var3  : chr "aa" "bb" "cc" "dd" ... 
$ var2.var2a: chr "v" "w" "x" "y" ... 
$ var2.var2b: chr "vv" "ww" "xx" "yy" ... 

Ist das näher an, was Sie suchen?

+0

Ja, danke, das löst das Problem und macht meine hacky Problemumgehung überflüssig. Allerdings würde ich gerne etwas genauer wissen, was genau vor sich geht. Wie nennt man diese Datenstruktur für Anfänger? Es ist nicht wirklich verschachtelt. – JanLauGe

+1

jsonlite vereinfacht die JSON-Arrays in einen verschachtelten Datenrahmen. Sie können dies ausschalten, indem Sie 'simplyDataFrame = F' sagen, aber stattdessen verschachtelte Listen zurückgeben. Es ist schwer zu sagen, ohne das json Textobjekt zu arbeiten, aber es scheint geschachtelt zu sein;) –

+0

Danke! Siehe mein Update für das Follow-up :) – JanLauGe

Verwandte Themen