【问题标题】:Make deeply nested JSON from data frame in R从R中的数据框制作深度嵌套的JSON
【发布时间】:2016-07-07 19:37:39
【问题描述】:

我正在寻找一个漂亮整洁的数据框,并使用 R 将其转换为深度嵌套的 JSON。到目前为止,我还没有找到任何其他直接解决此任务的资源 - 大多数似乎都在尝试将其转向另一个方向(取消嵌套 JSON)。

这是我开始使用的数据框的一个小虚拟版本。想象一下,对公司内的两个受众进行了一项调查,一个针对经理,另一个针对员工。调查有不同 ID 的不同问题集,但许多问题重叠,我想比较两组之间的回答。最终目标是生成一个 JSON,以匹配正确层次结构中两个调查的部分 ID、问题 ID 和选项 ID/文本。有些问题有需要进一步嵌套的子问题,这就是我很难做到的。

library(dplyr)
library(tidyr)
library(jsonlite)

dummyDF <- data_frame(sectionId = c(rep(1,9),rep(2,3)),
                      questionId = c(rep(1,3),rep(2,6),rep(3,3)),
                      subquestionId = c(rep(NA,3),rep("2a",3),rep("2b",3),rep(NA,3)),
                      deptManagerQId = c(rep("m1",3),rep("m2",3),rep("m3",3),rep("m4",3)),
                      deptEmployeeQId = c(rep("e1",3),rep("e3",3),rep("e4",3),rep("e7",3)),
                      optionId = rep(c(1,2,3),4),
                      text = rep(c("yes","neutral","no"),4))

这是我想要达到的最终结果:

theGoal <- fromJSON('{
  "sections": [
    {
      "sectionId": "1",
      "questions": [
        {
          "questionId": "1",
          "deptManagerQId": "m1",
          "deptEmployeeQId": "e1",
          "options": [
            {
              "optionId": 1,
              "text": "yes"
            },
            {
              "optionId": 2,
              "text": "neutral"
            },
            {
              "optionId": 3,
              "text": "no"
            }
          ]
        },
        {
          "questionId": "2",
          "options": [
            {
              "optionId": 1,
              "text": "yes"
            },
            {
              "optionId": 2,
              "text": "neutral"
            },
            {
              "optionId": 3,
              "text": "no"
            }
          ],
          "subquestions": [
            {
              "subquestionId": "2a",
              "deptManagerQId": "m2",
              "deptEmployeeQId": "e3"
            },
            {
              "subquestionId": "2b",
              "deptManagerQId": "m3",
              "deptEmployeeQId": "e4"
            }
          ]
        },
        {
          "questionId": "3",
          "deptManagerQId": "m4",
          "deptEmployeeQId": "e7",
          "options": [
            {
              "optionId": 1,
              "text": "yes"
            },
            {
              "optionId": 2,
              "text": "neutral"
            },
            {
              "optionId": 3,
              "text": "no"
            }
          ]
        }
      ]
    }
  ]
}')

以下是我尝试使用来自 tidyr 的 Nest 的几种方法,但最终要么只能让我走一部分路,要么抛出错误消息。

1

list1 <- dummyDF %>% nest(-sectionId, .key=questions) %>% 
  mutate(questions = lapply(seq_along(.$questions), function(x) nest(.$questions[[x]], optionId, text, .key = options))) %>%
  list(sections = .)

2

nested1 <- dummyDF %>% nest(-sectionId, .key=questions) %>% 
  mutate(questions = lapply(seq_along(.$questions), function(x) nest(.$questions[[x]], optionId, text, .key = options)))

nested2 <- nested1 %>% mutate(questions = lapply(seq_along(.$questions), function(x) nest(.$questions[[x]], subquestionId, .key = subquestions))) 
#Gives this error: cannot group column options, of class 'list'

3

list2 <- dummyDF %>% nest(-sectionId, .key=questions) %>% 
  mutate(questions = lapply(seq_along(.$questions), 
                            function(x) {ifelse(is.na(.$questions[[x]]$subquestionId),
                                                function(x) {.$questions[[x]] %>% select(-subquestionId) %>% nest(optionId, text, .key = options)},
                                                function(x) {.$questions[[x]] %>% nest(subquestion_id, .key = subquestions)})})) %>% 
  list(sections = .) 
#Gives this error: attempt to replicate an object of type 'closure'

任何想法将不胜感激。我对任何方法都持开放态度。我把这个问题带到了当地的 R 用户组聚会上,但无法提出任何解决方案,所以我在这里祈祷。我意识到 R 可能不是完成此任务的最佳工具,但它是我所知道的,所以我试一试。谢谢。

【问题讨论】:

  • 为什么第2题没有deptManagerQIddeptEmployeeQId
  • 只有叶问题具有与之关联的 deptManagerQId 和 deptEmployeeQId。问题 2 只是一个父级,在调查数据中没有任何直接关联的响应,仅通过它的子级 2a 和 2b。

标签: json r tidyr


【解决方案1】:

jsonlite::toJSON 看起来可以很好地解决您的问题。

无缝地工作到列类型和列顺序(我更正以说明对象是相同的)。如果您需要任何其他类型的 JSON 结构,我建议您首先使用 dplyrtidyr 之类的东西在前端重构 data_frame。

library(jsonlite)
library(dplyr)

dummyDF <- data_frame(sectionId = c(rep(1,9),rep(2,3)),
                  questionId = c(rep(1,3),rep(2,6),rep(3,3)),
                  subquestionId = c(rep(NA,3),rep("2a",3),rep("2b",3),rep(NA,3)),
                  deptManagerQId = c(rep("m1",3),rep("m2",3),rep("m3",3),rep("m4",3)),
                  deptEmployeeQId = c(rep("e1",3),rep("e3",3),rep("e4",3),rep("e7",3)),
                  optionId = rep(c(1,2,3),4),
                  text = rep(c("yes","neutral","no"),4))

## Convert to a JSON object
json <- jsonlite::toJSON(dummyDF)


theGoal <- fromJSON(json) %>% tbl_df() %>% select_(.dots=names(dummyDF)) %>%
  ## Convert integer columns to numeric
  mutate_if(function(x) {if (typeof(x)=='integer') {TRUE} else {FALSE}},as.numeric)

## Compare the objects
all.equal(theGoal,dummyDF)
# TRUE

identical(theGoal,dummyDF)
# TRUE

【讨论】:

    猜你喜欢
    • 2020-11-07
    • 2023-03-09
    • 1970-01-01
    • 2017-12-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-17
    相关资源
    最近更新 更多