【问题标题】:R networkD3 package: forceNetwork() coloringR networkD3 包:forceNetwork() 着色
【发布时间】:2017-07-19 01:09:01
【问题描述】:

我真的很喜欢这个网络的样子:

来源:https://christophergandrud.github.io/networkD3/

每个扇区有多种颜色,其中每种颜色代表网络中与其他节点相距足够远的节点的某些不同部分。

但是,在任何一个特定扇区中,我不喜欢 src 节点与 target 节点的颜色相同,因此我问了一个问题 (https://stackoverflow.com/a/35371131/3878253) 如何区分这两者颜色。

现在有没有一种方法可以扩展此代码以恢复多种配色方案(以区分各个扇区)同时保留漂亮的src/target 颜色差异?代码如下:

# Load package
library(networkD3)
library(dplyr) # to make the joins easier

# Create fake data
src <- c("A", "A", "A", "A",
         "B", "B", "C", "C", "D")
target <- c("B", "C", "D", "J",
            "E", "F", "G", "H", "I")
networkData <- data.frame(src, target, stringsAsFactors = FALSE)

nodes <- data.frame(name = unique(c(src, target)), stringsAsFactors = FALSE)
nodes$id <- 0:(nrow(nodes) - 1)


# create a data frame of the edges that uses id 0:9 instead of their names
edges <- networkData %>%
   left_join(nodes, by = c("src" = "name")) %>%
   select(-src) %>%
   rename(source = id) %>%
   left_join(nodes, by = c("target" = "name")) %>%
   select(-target) %>%
   rename(target = id)

edges$width <- 1

# make a grouping variable that will match to colours
nodes$group <- ifelse(nodes$name %in% src, "lions", "tigers")


ColourScale <- 'd3.scaleOrdinal()
            .domain(["lions", "tigers"])
           .range(["#FF6900", "#694489"]);'

forceNetwork(Links = edges, Nodes = nodes, 
             Source = "source",
             Target = "target",
             NodeID ="name",
             Group = "group",
             Value = "width",
             opacity = 0.9,
             zoom = TRUE,
             colourScale = JS(ColourScale))

【问题讨论】:

    标签: javascript r d3.js networkd3


    【解决方案1】:

    重新阅读您的问题和回复后,我认为您真正想知道的是……如何将您的数据分组。定义集群后,您可以将nodes 数据框中每个节点的组值设置为其集群的名称/ID,然后networkD3 将相应地为它们着色。

    进一步回答您的问题,尚不清楚您希望如何同时组合“不同颜色源和目标节点”“根据集群颜色节点”......这些目标显然是冲突的,因为集群包含源节点和目标节点。您的问题的另一个问题是,在这些类型的网络中,一个节点可能既是源节点又是目标节点,因此您必须更清楚地了解如何为它们着色。我可以假设您将“目标”节点定义为仅链接到另一个节点的节点(从技术上讲,节点是源还是目标取决于节点之间链接的方向),但这不是必然如此(我可以想象你可能有其他解释)。

    要进行集群,您需要查看igraph 包及其众多集群功能。比如……

    使用 networkD3 中包含的悲惨世界数据,让我们回溯到只有一个包含源字符和目标字符的两列数据框...

    library(igraph)
    library(networkD3)
    
    data(MisLinks)
    data(MisNodes)
    
    lesmis <- data.frame(source = MisNodes$name[MisLinks$source + 1], 
                         target = MisNodes$name[MisLinks$target + 1],
                         stringsAsFactors = F)
    

    现在,您可以使用 igraph 计算聚类,然后将它们重新组合在一起以绘制在 networkD3...

    lesmis <- graph_from_data_frame(lesmis)
    wc <- cluster_walktrap(lesmis)
    members <- membership(wc)
    
    lesmis <- igraph_to_networkD3(lesmis, group = members)
    
    forceNetwork(Links = lesmis$links, Nodes = lesmis$nodes, 
                 Source = 'source', Target = 'target', 
                 NodeID = 'name', Group = 'group', opacity = 1)
    

    现在,如果您想让“目标”节点(只有一个链接的节点)也具有不同的颜色,您可以找出哪些节点仅在源和目标列表中出现一次,并在nodes 数据框到独特的东西......

    allnodes <- c(lesmis$links$source, lesmis$links$target)
    targetids <- allnodes[!duplicated(allnodes) & ! duplicated(allnodes, fromLast = T)]
    lesmis$nodes$group[targetids + 1] <- 'target'
    
    forceNetwork(Links = lesmis$links, Nodes = lesmis$nodes, 
                 Source = 'source', Target = 'target', 
                 NodeID = 'name', Group = 'group', opacity = 1)
    

    【讨论】:

      【解决方案2】:

      Nodes 数据框中的group 列决定了颜色。您可以为每个节点设置group 值(手动或其他方式),networkD3 将根据调色板为每组节点着色。

      比如……

      edges <- read.table(header = T, text = '
      source target width
      0      1     1
      0      2     1
      0      3     1
      0      4     1
      1      5     1
      1      6     1
      2      7     1
      2      8     1
      3      9     1
      ')
      
      nodes <- read.table(header = T, text = '
      name id  group
      A    0   panther
      B    1   leopard
      C    2   tiger
      D    3   lion
      J    4   panthercub
      E    5   leopardcub
      F    6   leopardcub
      G    7   tigercub
      H    8   tigercub
      I    9   lioncub
      ')
      
      forceNetwork(Links = edges, Nodes = nodes, 
                   Source = "source",
                   Target = "target",
                   NodeID ="name",
                   Group = "group",
                   Value = "width",
                   opacity = 0.9,
                   zoom = TRUE,
                   colourScale = JS("d3.scaleOrdinal(d3.schemeCategory10);"))
      

      【讨论】:

      • 如您所述,此解决方案需要在nodes 数据框的group 列中手动设置值。但是,我想问是否有办法让这个过程自动化,让源代码自动为您着色网络的各个部分。在更大的网络中,这将是一个很大的优势(即,它会非常好且可扩展)。不过我喜欢你的回答,因为它首先说明了着色概念的来源。
      • 您可以预处理节点数据框,以您想要的任何方式设置组值。如果你给出一个具体的用例,我也许可以帮你做,但是在不知道具体情况的情况下,几乎有无限的可能性。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-05-18
      • 1970-01-01
      • 2022-08-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多