Javascript 将JSON格式转换为CSV,在R中上传数据表,生成D3气泡图

Javascript 将JSON格式转换为CSV,在R中上传数据表,生成D3气泡图,javascript,json,r,csv,d3.js,Javascript,Json,R,Csv,D3.js,我正在尝试使用in R来制作我自己的气泡图,并将气泡颜色分组 我已经将index.html和flare.json文件从D3上传到R中,它在运行时生成了气泡图。但我不想手动更改此JSON代码来创建我自己的气泡和组(下面的标题显示了一组3个气泡组,其中包含不同组的名称) 使用jsonlite包(在线阅读可以处理更复杂的json结构),我已经将其转换为数据帧 library(jsonlite) fromJSON("flare.json",simplifyDateframe = FALSE) 这是

我正在尝试使用in R来制作我自己的气泡图,并将气泡颜色分组

我已经将index.html和flare.json文件从D3上传到R中,它在运行时生成了气泡图。但我不想手动更改此JSON代码来创建我自己的气泡和组(下面的标题显示了一组3个气泡组,其中包含不同组的名称)

使用jsonlite包(在线阅读可以处理更复杂的json结构),我已经将其转换为数据帧

 library(jsonlite)
 fromJSON("flare.json",simplifyDateframe = FALSE)
这是没有请求的数据帧结构(示例)

这是带有请求的数据帧结构的(示例)

然而,它产生了一个长串接的数据列表,我一直在尝试解开这个列表,以使数据自动化

Arrays, Colors, Dates, Displays, Filter, Geometry, heap, IEvaluable,  IPredicate, IValueProxy, math, Maths, Orientation, palette, Property, Shapes, Sort, Stats, Strings, 8258, 10001, 8217, 12555, 2324, 10993, NA, 335, 383, 874, NA, 17705, 1486, NA, 5559, 19118, 6887, 6557, 22026, FibonacciHeap, HeapNode, 9354, 1233, DenseMatrix, IMatrix, SparseMatrix, 3165, 2815, 3366, ColorPalette, Palette, ShapePalette, SizePalette, 6367, 1229, 2059, 2291
建议的解决方案

对于循环(时间限制)

我曾考虑过编写多个for循环来重新构造JSON嵌套结构(我更擅长于此,但我有一个最后期限,这可能需要一段时间)。但我想,一个更懂JSON的人也许能帮上忙

CSV转换格式(不工作)

我还尝试使用convertor转换flare.json文件,以生成测试是否可以将CSV中的内容直接更新到R中所需的CSV格式,但这不起作用(即使添加了flare.json头内容,也无法从jsonlite自动更新到json)

我真正需要的 一种将flare.json从json转换为数据帧或表的解决方案,以便我可以将包含名称、大小和组的数据上传到转换回json,以生成我自己的气泡图

如果可能的话,这将是伟大的,以实现这一切在R,我不认为是不可能的,但我很高兴听到其他建议


我很困惑下一步该怎么办。我通常在R中处理矩阵,因此处理JSON列表和数组不是我的强项。

发布此文章只是为了进一步讨论。正如@ TimelyPosiple所说的,有相当多的事情要考虑。这里有一条路径(目前只从“flare”JSON到一个长数据帧,直到我们得到更多您想要的内容)

library(jsonlite)
图书馆(dplyr)
图书馆(tidyr)
flare%distinct%>%打印(n=1000)
##来源:本地数据帧[10 x 1]
## 
##名字
##1分析
##2制作动画
##3数据
##4显示器
##5弹性体
##6物理学
##7查询
##8比例尺
##9 util
##10 vis

将数据帧的格式展开为“flare”非常简单,但对于您的操作来说,这可能不是一种可用的数据帧格式。

这可能会为我们提供一些其他需要考虑的问题。我将把注释内联到代码中。你可以看到一个

library(jsonlite)
图书馆(dplyr)

flare_json感谢@timelyportfolio为我指出这一点。使用data.tree包(需要github的最新版本)可以非常简单地实现从data.frame/json到data.frame/json的转换。诀窍是将路径粘贴在一起:

#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)
#devtools::install_github(“gluc/data.tree”)
libraray(data.tree)

df我想一个初始问题是“您认为数据帧的结构是什么?”?有一篇关于从数据帧转换为“flare”格式的博客文章——但我不确定这是否是您希望能够使用的数据帧结构。这些毛茸茸的野兽一开始可能很困难,但您很快就会轻松地完成它们。如果可以的话,我们能再退一步吗?虽然使用flare.json重新创建bl.ocks示例很有趣,但您预期的用例是什么?R(边列表、邻接矩阵、data.frame)中的源数据是什么,您希望插入到圆形压缩图表中?我在想,我们只是从中得到一个htmlwidget来解决我们所有的问题:)现在,我将使用flare.json来处理json->R->json管道的一些示例。(这将是一个有趣的SO线程:-)@hrbrmstr感谢这个链接很有用。我想这不是关于节点的问题,而是关于分组的问题。@timelyportfolio所以这里是我的用户案例。我想表示来自不同数据源的数据大小。例如,我有社交媒体关注者(Facebook 10000、Twitter 5000、Youtube 200),这是一个群体,另一个群体可能是网络视图(网站10000、次要网站2500)。然后这两个组是在线数据,因此被分组。所以我真的想要一个表格,我可以把数据源名称(Facebook)、大小(10000)、主要群组(社交媒体)、整个群组(在线)然后要转换为正确的JSON格式,如R中的flare?另外两个将R数据结构转换为嵌套d3格式的示例
data.tree
networkD3
,在这个截止日期,我不得不使用bubbles小部件,但必须删除文本,因为它不可读,并且没有使用bubble定位文本。这个小部件已经6个月没用了,不知道有什么开发计划。所以我仍然需要将flare的转换表恢复为json格式,以便在索引中使用,比如flare.json->table.csv->newdata.json->newdata bubbles using index.htmlany这样我们就可以从现在开始忽略flare并使用真实/示例数据,因为flare不是您希望使用的数据?您是否仍然希望从JSON开始?从R开始,使用R结构并在最后转换是非常容易的;有一个htmlwidget开始,但它仍然需要一些工作。使用编辑小部件查看JSON是一个很好的技巧!!谢谢
 fromJSON("flare.json",simplifyDataFrame = TRUE)
Arrays, Colors, Dates, Displays, Filter, Geometry, heap, IEvaluable,  IPredicate, IValueProxy, math, Maths, Orientation, palette, Property, Shapes, Sort, Stats, Strings, 8258, 10001, 8217, 12555, 2324, 10993, NA, 335, 383, 874, NA, 17705, 1486, NA, 5559, 19118, 6887, 6557, 22026, FibonacciHeap, HeapNode, 9354, 1233, DenseMatrix, IMatrix, SparseMatrix, 3165, 2815, 3366, ColorPalette, Palette, ShapePalette, SizePalette, 6367, 1229, 2059, 2291
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
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
#  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)
#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)