json - 具有不规则节点的分层 data.frame 到 JSON

标签 json r

我有这个嵌套数据集:

grandparent,parent,child,grandchild,age
Grandma,,,,100
Grandma,John,,,72
Grandma,John,Jessica,,41
Grandma,John,Joanne,,35
Grandma,Mary,,,70
Grandma,Mary,Max,,39
Grandma,Mary,Max,Ken,12
Grandma,Mary,Max,Kate,19
Grandma,Mary,Max,Karl,8
Grandma,Mary,Millie,Peter,2
Grandma,Mary,Millie,Pat,11
Grandma,Mary,Millie,Pam,24
Grandma,Dave,,,66
Grandma,Dave,Doloris,,32
Grandma,Dave,Dana,,23
Grandma,Dave,Daniel,,13

我想将其转换为 hierarchical JSON 结构,如 flare.json对于 D3.js,尽管在每个节点都保留值“age”,如下所示。我知道这个主题并不完全新颖 - 但我还没有看到任何节点可以不规则并获取每个节点的值的解决方案..

{
 "name":"Grandma",
 "age": 100,
 "children":[
   {
     "name":"John",
      "age": 72,
     "children":[
        {
           "name":"Jessica",
           "age": 41
        },
        {
           "name":"Joanne",
           "age": 35
        }
    ]   
},
    {
     "name":"Mary",
     "age": 70,
     "children":[
        {
           "name":"Max",
           "age": 39
            "children":[
                {
                   "name":"Ken",
                   "age":12
                },
                {
                   "name":"Kate",
                   "age":19
                },
                {
                   "name":"Karl",
                   "age":8
                }
             ]
        },
        {
           "name":"Millie",
           "age":43,
           "children":[
                {
                   "name":"Peter",
                   "age":2
                },
                {
                   "name":"Pat",
                   "age":11
                },
                {
                   "name":"Pam",
                   "age":24
                }
             ]
        }
     ]
  },
  {
     "name":"Dave",
     "age": 66,
     "children":[
        {
           "name":"Doloris",
           "age":32
        },
        {
           "name":"Dana",
           "age":23
        },
        {
           "name":"Daniel",
           "age":13
        }
     ]
  }
  ]
 }

数据框:

structure(list(grandparent = structure(c(1L, 1L, 1L, 1L, 1L, 
    1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L), .Label = "Grandma", class = "factor"), 
        parent = structure(c(1L, 3L, 3L, 3L, 4L, 4L, 4L, 4L, 4L, 
        4L, 4L, 4L, 2L, 2L, 2L, 2L), .Label = c("", "Dave", "John", 
        "Mary"), class = "factor"), child = structure(c(1L, 1L, 5L, 
        6L, 1L, 7L, 7L, 7L, 7L, 8L, 8L, 8L, 1L, 4L, 2L, 3L), .Label = c("", 
        "Dana", "Daniel", "Doloris", "Jessica", "Joanne", "Max", 
        "Millie"), class = "factor"), grandchild = structure(c(1L, 
        1L, 1L, 1L, 1L, 1L, 4L, 3L, 2L, 7L, 6L, 5L, 1L, 1L, 1L, 1L
        ), .Label = c("", "Karl", "Kate", "Ken", "Pam", "Pat", "Peter"
        ), class = "factor"), age = c(100L, 72L, 41L, 35L, 70L, 39L, 
        12L, 19L, 8L, 2L, 11L, 24L, 66L, 32L, 23L, 13L)), .Names = c("grandparent", 
    "parent", "child", "grandchild", "age"), class = "data.frame", row.names = c(NA, 
    -16L))

最佳答案

在调用 toJSON 之前,您需要将 data.frame 转换为参差不齐的列表。尝试以下操作

library(toJSON)
library(data.table)

# Convert the data.frame to data.table for ease of handling
DT <- data.table(D)  # assuming `D` is your original data.frame

rList <- list()
parent <- list()
child <- list()
grandchild <- list()

j <- 1
while (j < nrow(DT)) {
  lastj <- j

  while (DT[j, parent=="" && grandparent != ""]) {
    rList[[length(rList)+1]] <- as.list(DT[j, list(name=grandparent, age)])
    j <- j+1
  }

  while (DT[j, child==""] && DT[(j-1):j, identical(grandparent[[1]], grandparent[[2]])]  && (j < nrow(DT)) ) {
    parent[[length(parent)+1]] <- as.list(DT[j, list(name=parent, age)])
    j <- j+1
  }

  while(DT[j, grandchild==""] && DT[(j-1):j, identical(parent[[1]], parent[[2]])]  && (j < nrow(DT)) ) {
    child[[length(child)+1]] <- as.list(DT[j, list(name=child, age)])
    j <- j+1
  }

  while(DT[j, grandchild!="" ] && DT[(j-1):j, identical(child[[1]], child[[2]])]  && (j < nrow(DT)) ) {
    grandchild[[length(grandchild)+1]] <- as.list(DT[j, list(name=grandchild, age)])
    j <- j+1
  }

  if (length(grandchild)) {
    child[[length(child)]][["children"]] <- grandchild
#    grandchild <- list() # reset
  }
  if (length(child)) {
    parent[[length(parent)]][["children"]] <- child
#    child <- list()
  }
  if (length(parent)) {
    rList[[length(rList)]][["children"]] <- parent
#    parent <- list()
  }

  cat ("\tat end, j  = ", j, "\n")

  # if j wasn't incremented throughout the whole loop, do so now. (This will happen when there is a change in the penultimate level)
  if (j == lastj)
    j <- j+1

}

RESULTS <- toJSON(rList)

结果:

cat(gsub("\\{","\n\\{", RESULTS))

[
{"name":"Grandma","age":100,"children":[
{"name":"John","age":72,"children":[
{"name":"Jessica","age":41},
{"name":"Joanne","age":35}]},
{"name":"Mary","age":70,"children":[
{"name":"Jessica","age":41},
{"name":"Joanne","age":35},
{"name":"Max","age":39,"children":[
{"name":"Ken","age":12},
{"name":"Kate","age":19},
{"name":"Karl","age":8},
{"name":"Pat","age":11},
{"name":"Pam","age":24}]}]},
{"name":"Dave","age":66,"children":[
{"name":"Jessica","age":41},
{"name":"Joanne","age":35},
{"name":"Max","age":39,"children":[
{"name":"Ken","age":12},
{"name":"Kate","age":19},
{"name":"Karl","age":8},
{"name":"Pat","age":11},
{"name":"Pam","age":24}]},
{"name":"Doloris","age":32},
{"name":"Dana","age":23,"children":[
{"name":"Ken","age":12},
{"name":"Kate","age":19},
{"name":"Karl","age":8},
{"name":"Pat","age":11},
{"name":"Pam","age":24}]}]}]}]   

关于json - 具有不规则节点的分层 data.frame 到 JSON,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17951334/

相关文章:

r - 如何在数字序列的循环内的赋值运算符的两侧使用paste0?

r - 选择至少具有某一特定值之一的组

r - 如何从我的包内加载另一个包的数据

javascript - 发送 JSON 到服务器

r - 如何使用 graph.coreness 找到顶点所属的最大 k-core

javascript - 在 JavaScript 中获取 JSON 对象的最后一个元素

android - 如何使用动态响应键解析 json

r - 基于另一个数据框的两行比较

c# - 根据属性的运行时值选择性地序列化属性

javascript - 从数组中对象的数组中获取字符串值