score:1

Posting this only for further discussion. As @timelyportfolio said, there's quite a bit to consider. Here's one path (only going from "flare" JSON to a long data frame for now until we get more of what you're looking for).

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

flare <- fromJSON("http://bl.ocks.org/mbostock/raw/4063269/flare.json",
                          simplifyVector=FALSE)

flare_df <- bind_rows(lapply(flare$children,
    function(x) {
      kids <- as.list(x)
      kids$stringsAsFactors=FALSE # prevents bind_rows warnings
      do.call("data.frame", kids)
    }
)) %>% gather(child_path, value, -name)

set.seed(1492) # results reproducibility
print(flare_df[sample(nrow(flare_df), 50),])

## Source: local data frame [50 x 3]
## 
##       name                         child_path value
## 1  display                   children.name.18    NA
## 2     util                   children.size.11  5559
## 3  display                    children.name.9    NA
## 4  display           children.children.size.9    NA
## 5  physics           children.children.name.4    NA
## 6    query             children.children.name   add
## 7  physics children.children.children.size.22    NA
## 8     data                   children.name.20    NA
## 9      vis          children.children.size.20 19382
## 10    flex          children.children.name.36    NA
## ..     ...                                ...   ...

# just showing the top-level nodes are present for an example

select(flare_df, name) %>% arrange(name) %>% distinct %>% print(n=1000)

## Source: local data frame [10 x 1]
## 
##         name
## 1  analytics
## 2    animate
## 3       data
## 4    display
## 5       flex
## 6    physics
## 7      query
## 8      scale
## 9       util
## 10       vis

Unwrapping that for data frame to "flare" is pretty straightforward, but that may not be a usable data frame format for your manipulation.

score:1

Thanks to @timelyportfolio for pointing me to this. You can achieve conversion from and to data.frame / json quite simply with the data.tree package (latest from github required). The trick is to paste together a path:

#devtools::install_github("gluc/data.tree")
libraray(data.tree)

df <- data.frame(
  "overallgroup" = "Online"
  ,"primarygroup" = c(rep("Social Media",3),rep("Web",2))
  ,"datasource" = c("Facebook","Twitter","Youtube","Website","Secondary Website")
  ,"size" = c(10000,5000,200,10000,2500)
  ,stringsAsFactors = FALSE
)


df$pathString <- paste("root", df$overallgroup, df$primarygroup, df$datasource, sep="/")
root <- as.Node(df[,-c(1, 2, 3)])

# now we should be able to supply root to networkD3
#   that expects a typical d3 nested JSON
#devtools::install_github("christophergandrud/networkD3")
library(networkD3)
treeNetwork( root$ToList(unname=TRUE) )

# or to get it in JSON
jsonlite::toJSON( root$ToList(unname=TRUE), auto_unbox=TRUE)

score:5

This might provide us something else to think about. I'll put comments inline in the code. You can see a live example.

library(jsonlite)
library(dplyr)


flare_json <- rjson::fromJSON(  ## rjson just works better on these for me
    file = "http://bl.ocks.org/mbostock/raw/4063269/flare.json"
)

# let's have a look at the structure of flare.json
# listviewer htmlwidget might help us see what is happening
#   devtools::install_github("timelyportfolio/listviewer")
#   library(listviewer)
jsonedit(
  paste0(
    readLines("http://bl.ocks.org/mbostock/raw/4063269/flare.json")
    ,collapse=""
  )
)

# the interesting thing about Mike Bostock's Bubble Chart example
#   though is that the example removes the nested hierarchy
#    with a JavaScript function called classes
#// Returns a flattened hierarchy containing all leaf nodes under the root.
#function classes(root) {
#  var classes = [];
#  
#  function recurse(name, node) {
#    if (node.children) node.children.forEach(function(child) { recurse(node.name, child); });
#    else classes.push({packageName: name, className: node.name, value: node.size});
#  }
#  
#  recurse(null, root);
#  return {children: classes};
#}

# let's try to recreate this in R
classes <- function(root){
  classes <- data.frame()

  haschild <- function(node){
    (!is.null(node) && "children" %in% names(node))
  }

  recurse <- function(name,node){
    if(haschild(node)){
      lapply(
        1:length(node$children)
        ,function(n){
          recurse(node$name,node$children[[n]])
        }
      )
    } else {
      classes <<- bind_rows(
        classes,
        data.frame(
          "packageName"= name
          ,"className" = node[["name"]]
          ,"size" = node[["size"]]
          ,stringsAsFactors = F
        )
      )
    }
  }

  recurse(root$name,root)
  return(classes)
}

# now with a R flavor our class replica should work
flare_df <- classes(flare_json)


# so the example uses a data.frame with columns
#   packageName, className, size
# and feeds that to bubble.nodes where bubble = d3.layout.pack
# fortunately Joe Cheng has already made a htmlwidget called bubbles
#   https://github.com/jcheng5/bubbles
# that will produce a d3.layout.pack bubble chart

library(scales)

bubbles(
  flare_df$size
  ,flare_df$className
  ,color = col_factor(
    RColorBrewer::brewer.pal(9,"Set1")
    ,factor(flare_df$packageName)
  )(flare_df$packageName)
  ,height = 600
  ,width = 960
)

# it's not perfect with things such as text sizing
#    but it's a start

If you still think you want a nested d3 JSON hierarchy, here is some code.

#  convert this to nested d3 json format
#    this is example data provided in a comment to this post
df <- data.frame(
  "overallgroup" = "Online"
  ,"primarygroup" = c(rep("Social Media",3),rep("Web",2))
  ,"datasource" = c("Facebook","Twitter","Youtube","Website","Secondary Website")
  ,"size" = c(10000,5000,200,10000,2500)
  ,stringsAsFactors = FALSE
)


# recommend using data.tree to ease our pain here
#devtools::install_github("gluc/data.tree")
library(data.tree)

# the much easier way
df$pathString <- apply(df[,1:3],MARGIN=1, function(x){paste0(x,collapse="/")})
root <- as.Node(df[,4:5])    

# the harder manual way
root <- Node$new("root")
sapply(unique(df[,1]),root$AddChild)
apply(
  df[,1:ncol(df)]
  ,MARGIN = 1
  ,function(row){
    lapply(2:length(row),function(cellnum){
      cell <- row[cellnum]
      if( cellnum < ncol(df) ){ # assume last column is attribute
        parent <- Reduce(function(x,y){x$Climb(y)},as.character(row[1:(cellnum-1)]),root)
        if(is.null(parent$Climb(cell))){
          cellnode <- parent$AddChild( cell )
        }  
      } else{
        cellnode <- Reduce(function(x,y){x$Climb(y)},as.character(row[1:(cellnum-1)]),root)
        cellnode$Set( size = as.numeric(cell) )
      }
    })
  }
)


# now we should be able to supply root to networkD3
#   that expects a typical d3 nested JSON
#devtools::install_github("christophergandrud/networkD3")
library(networkD3)
treeNetwork( root$ToList(unname=TRUE) )

# or to get it in JSON
jsonlite::toJSON( root$ToList(unname=TRUE), auto_unbox=TRUE)

Related Query

More Query from same tag