Converting nested JSON to data frame

2019-07-26 10:19发布

问题:

I am trying to convert a heavily nested json into a proper data frame (proper by tidy standards). An MWE of the json is copied at the end of the question, as I wanted to make sure it captured every element of the json.

I've tried:

library(jsonlite)
library(tidyverse)
dat <- jsonlite::fromJSON('data_toy.json') %>% pluck(1) %>% imap_dfr(~mutate(.x, department = .y))

but this returns:

Error: Columns `time_spent`, `school_breakdown`, `reason_for_taking_course`, `student_years`, `interest_before` must be 1d atomic vectors or lists

I've also tried:

dat <- jsonlite::fromJSON('data_toy.json', simplifyVector = FALSE, 
                          simplifyDataFrame = FALSE, flatten=FALSE)
dat.df <- map_df(dat, ~{
  flatten_df(.x[[1]]) %>%
    dplyr::mutate(department = names(.x)[1])
})

but this returns:

Error in bind_rows_(x, .id) : Argument 3 must be length 1, not 0

How can I convert this to a data frame?

Data file (data_toy.json):

{
    "department": {
        "BME": [
            {
                "course_name": "BMD_ENG_250-0_20: Thermodynamics",
                "instructor": "Neha Kamat",
                "time_spent": {},
                "school_breakdown": {
                    "Education & SP": 0,
                    "Communication": 0,
                    "Graduate School": 0,
                    "KGSM": 0
                },
                "reason_for_taking_course": {
                    "Distribution requirement": 0,
                    "Major/Minor requirement": 53
                },
                "student_years": {
                    "Freshman": 5,
                    "Sophomore": 37
                },
                "interest_before": {
                    "1-Not interested at all": 1,
                    "2": 5
                },
                "comments": [
                    "is amazing and you will love her!",
                    "Prof. is so nice"
                ],
                "instructor_gender": "F"
            },
            {
                "course_name": "BMD_ENG_250-0_20: Thermodynamics",
                "instructor": "Neha Kamat",
                "time_spent": {},
                "school_breakdown": {
                    "Education & SP": 0,
                    "Communication": 0,
                    "Graduate School": 0,
                    "KGSM": 0
                },
                "reason_for_taking_course": {
                    "Distribution requirement": 0,
                    "Major/Minor requirement": 53
                },
                "student_years": {
                    "Freshman": 5,
                    "Sophomore": 37
                },
                "interest_before": {
                    "1-Not interested at all": 1,
                    "2": 5
                },
                "comments": [
                    "is amazing and you will love her!",
                    "Prof. is so nice"
                ],
                "instructor_gender": "F"
            }
        ],
        "LING": [
            {
                "course_name": "BMD_ENG_250-0_20: Thermodynamics",
                "instructor": "Neha Kamat",
                "time_spent": {},
                "school_breakdown": {
                    "Education & SP": 0,
                    "Communication": 0,
                    "Graduate School": 0,
                    "KGSM": 0
                },
                "reason_for_taking_course": {
                    "Distribution requirement": 0,
                    "Major/Minor requirement": 53
                },
                "student_years": {
                    "Freshman": 5,
                    "Sophomore": 37
                },
                "interest_before": {
                    "1-Not interested at all": 1,
                    "2": 5
                },
                "comments": [
                    "is amazing and you will love her!",
                    "Prof. is so nice"
                ],
                "instructor_gender": "F"
            },
            {
                "course_name": "BMD_ENG_250-0_20: Thermodynamics",
                "instructor": "Neha Kamat",
                "time_spent": {},
                "school_breakdown": {
                    "Education & SP": 0,
                    "Communication": 0,
                    "Graduate School": 0,
                    "KGSM": 0
                },
                "reason_for_taking_course": {
                    "Distribution requirement": 0,
                    "Major/Minor requirement": 53
                },
                "student_years": {
                    "Freshman": 5,
                    "Sophomore": 37
                },
                "interest_before": {
                    "1-Not interested at all": 1,
                    "2": 5
                },
                "comments": [
                    "is amazing and you will love her!",
                    "Prof. is so nice"
                ],
                "instructor_gender": "F"
            }
        ]
    }
}

回答1:

Using flatten = TRUE seems to be the key here:

dat <- jsonlite::fromJSON('data_toy.json', flatten = TRUE)[[1]]
dat %>% bind_rows() %>% mutate(department = rep(names(dat), map_dbl(dat, nrow)))


标签: r json jsonlite