R - visNetwork在Shiny应用中与networkd3相比的最新性能表现(2017)

4
我希望能在一个“大”图(少于500个节点)上根据它们的中心性对顶点进行颜色标记,并允许用户在单击事件上删除边缘或顶点。当删除顶点或边缘时,将重新计算图上的新中心性分数,并再次呈现边缘和顶点的颜色。
我一直在研究visNetworknetworkD3 R包。这篇2015年的博客文章提到visNetwork比networkD3更具特色,但我阅读了几个SO问题,提到networkD3已经改变并扩展了其功能。
在这两个包中,哪一个更容易满足我的要求?

多大才算大? - Mike Wise
networkD3不直接支持该级别的定制化。 - CJ Yetman
@MikeWise 实际上,不到500个节点。 - andandandand
注意,有两个D3软件包,d3networknetworkD3软件包,它们都是用于网络的D3到R的端口。令人困惑。 - Mike Wise
Mike,我在这里注意到了,https://christophergandrud.github.io/d3Network/ "注意:开发已经转移到networkD3。d3Network不再受支持。" - FatihSarigol
1个回答

17

你知道的,我需要了解这个问题,因为我正在开始一个项目,而要真正了解它的唯一方法就是亲自尝试。

所以我写了一个应用程序。

library(shiny)
library(ggplot2)
library(visNetwork)
library(networkD3)
library(RColorBrewer)
set.seed(123)

u <- shinyUI(fluidPage(
  titlePanel("Network Library Comparison"),

  sidebarLayout(position = "left",
    sidebarPanel( h2("Parameters"),
      selectInput("mode","Network:",c("MisNodes","Random","Circular"),"Random"),
      numericInput("nnodes","Nodes:",10,1,10000,1),
      sliderInput("edgefak","Edge Factor:",0,10,2,step=0.1),
      numericInput("ngroups","Groups:",5,1,11,1),
      actionButton("gennet","Generate"),
      textOutput("networkstat")
    ),
  mainPanel(h2("Network Plots"),
    tabsetPanel(
      tabPanel("networkD3", forceNetworkOutput("networkD3",,height="500px"),
                                           style = "background-color: #eeeeee;"),
      tabPanel("visNetwork",visNetworkOutput("visnetwork",height="500px"),
                                            style = "background-color: #eeeeee;")
    )
   )
  )
))

#MisLinks and MisNodes are a standard example from networkD3
data(MisLinks)
data(MisNodes)
fmtarrstr <- function(arr){
  # first add ' surrounding every element
  qarr <- sprintf("'%s'",as.character(arr))
  # now concactinate them together seperated with ,
  paste(qarr,collapse=",")
}
clrpal <- brewer.pal(n=11,name="Spectral")
clrscale <- sprintf('d3.scaleOrdinal() .domain([%s]) .range([%s]);',
                                       fmtarrstr(1:11),fmtarrstr(clrpal))


s <- shinyServer(function(input, output){


  net <- reactiveValues(nodes=NULL,edges=NULL,groups=NULL)

  observeEvent(input$gennet,{
    print("regenerating network")
    mode <- input$mode
    nn <- input$nnodes
    ng <- input$ngroups
    edgefak <- input$edgefak
    if(mode=="MisNodes"){
      nodes <- data.frame(id = 0:(nrow(MisNodes)-1),
                          label=MisNodes$name,
                          title=MisNodes$name,
                          group=MisNodes$group,
                          color=clrpal[MisNodes$group+1],
                          size=MisNodes$size)
      edges <- data.frame(from = MisLinks$source, to = MisLinks$target)
      net$groups <- data.frame(id=1:11,colors<-clrpal[1:11])
    } else if(mode=="Random"){
      nodes <- data.frame(id = 0:(nn-1),
                          label=0:(nn-1),
                          title=0:(nn-1),
                          group=sample(0:(ng-1),nn,replace=T),
                          size=10)
      nodes$color <- clrpal[nodes$group+1]
      nedge <- trunc(nn*edgefak)
      frvek <- sample(0:(nn-1),nedge,replace=T)
      tovek <- sample(0:(nn-1),nedge,replace=T)
      edges <- data.frame(from = frvek, to = tovek)
      net$groups <- data.frame(id=1:ng,colors<-clrpal[1:ng])
    } else if(mode=="Circular"){

      nodes <- data.frame(id = 0:(nn-1),
                          label=0:(nn-1),
                          title=0:(nn-1),
                          group=sample(0:(ng-1),nn,replace=T),
                         size=10)
      nodes$color <- clrpal[nodes$group+1]
      nedge <- nn
      frvek <- 0:(nn-1)
      tovek <- c(1:(nn-1),0)
      edges <- data.frame(from = frvek, to = tovek)
      net$groups <- data.frame(id=1:ng,colors<-clrpal[1:ng])
    }
    net$nodes <- nodes
    net$edges <- edges
    net$groups <- data.frame(id=1:ng,colors<-clrpal[1:ng])
  })
  output$visnetwork <- renderVisNetwork({ 
    req(net$edges)
    netout <- visNetwork(net$nodes,net$edges) 
    netout
  })
  output$networkD3 <- renderForceNetwork({ 
    req(net$edges)
    netout <- forceNetwork(
      Links  = net$edges, Nodes   = net$nodes,
      Source = "from", Target  = "to",
      NodeID  = "label", Nodesize="size",
      Group="group",opacity=1.0, zoom=T, fontSize = 12,
      colourScale = JS(clrscale)) 
    netout
  })
  output$networkstat <- renderText({
    sprintf("\nNodes:%d  Edges:%d Groups:%d",
              nrow(net$nodes),nrow(net$edges),nrow(net$groups))
  })
})
shinyApp(u,s)

看起来像这样:

enter image description here

总的来说,我认为它们都有优点和缺点,但总体而言,visNetwork更易于使用,并且通过那些样条曲线看起来更酷,但对于更大的网络,networkD3初始化速度肯定更快。在200个节点的初始化过程中,visNetwork已经开始变得痛苦,但一旦绘制完成就没问题了。

注意事项:

  • networkD3鼠标缩放仅适用于真正的浏览器(我正在使用Chrome)。我无法让它在R-Studio浏览器中运行。让我发疯了。
  • 同样地,与R-Studio浏览器相比,Chrome中的所有内容都明显更快。在真正的浏览器中进行基准测试和实际工作。

“vis.js” 的坐标算法确实不是最快的。但你可以通过以下方式进行改进:在渲染“visIgraphLayout()”之前使用“igraph”计算坐标,查看稳定期间的网络“visPhysics(stabilization = FALSE)”,或/和禁用平滑边缘“visEdges(smooth = FALSE)”,最后可以尝试调整物理效果“?visPhysics”。 - bthieurmel
如果您还能添加其他框架,如cytoscape和threejs,那就太好了。 - skan
1
我可能会。我花了相当多的时间和精力在这上面,但从点赞和浏览量来看,它并不是一个热门话题。 - Mike Wise

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接