【问题标题】:R networkD3 package: node coloring in simpleNetwork()R networkD3 包:simpleNetwork() 中的节点着色
【发布时间】:2016-05-18 17:45:20
【问题描述】:

networkD3 包(参见herehere)允许用户创建简单的交互式网络:

# Load package
library(networkD3)

# 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)

# Plot
simpleNetwork(networkData)

有没有办法指定我希望src 向量中的所有元素都具有某种颜色,同时允许target 向量中的所有元素具有不同的颜色?这将使我能够直观地区分网络中的src 节点和target 节点。

simpleNetwork() 目前似乎不支持此功能(但我希望有人可以通过自制脚本帮助我):

一个类似但不相关的问题是asked here

【问题讨论】:

  • 可以在同一个包中使用forceNetwork()吗?您可以通过 Group 和 JavaScript 比例控制颜色。如果你愿意,我可以做一个完整的答案。
  • @PeterEllis 是的,这会很有帮助。
  • 可能是一个相关问题,即必须使用预先指定的颜色为节点着色:stackoverflow.com/questions/38793947/…

标签: javascript r htmlwidgets networkd3


【解决方案1】:

您可以执行与链接帖子中类似的操作,但这里是使用 visNetwork 包的示例。这个包与 vis.js 接口,并制作了非常好的交互式图表。

library(visNetwork)
id <- unique(c(src, target))                                  # node ids
nodes <- data.frame(id, group=+(id %in% src),                 # add a grouping for src/target
  label=id, title=sprintf('<p>Node %s</p>', id))              # add some labels
g <- visNetwork(nodes=nodes, edges=networkData, width="75%")  # make graph
visExport(visHierarchicalLayout(g))                           # make it tree-like

【讨论】:

  • 非常酷。我当然希望你在networkD3 中找到类似的东西:-) +1
【解决方案2】:

以下是使用forceNetwork 控制节点颜色的方法。请注意,这仍然不会告诉您链接的方向,因为某些节点是某些链接的源和其他链接的目标-因此您需要以某种方式重新考虑该逻辑。但无论如何,这里是控制节点的颜色。

# 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")

# simple with default colours
forceNetwork(Links = edges, Nodes = nodes, 
             Source = "source",
             Target = "target",
             NodeID ="name",
             Group = "group",
             Value = "width",
             opacity = 0.9,
             zoom = TRUE)

# control colours with a JS ordinal scale
# edited 20 May 2017 with updated code from Renal Chesak's answer:
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))

【讨论】:

  • 最好将节点全部标记。您能否扩展您的答案以显示如何使节点(srctarget)自动显示其名称,而不是仅在悬停时可访问性?
  • 为此有一个名为opacityNoHover 的参数。使用opacityNoHover = 1 始终显示节点标签。
【解决方案3】:

Peter Ellis 的上述回答可能曾经有效,但似乎代码已在新版本中更新。而不是d3.scale.ordinal().range([]),您必须使用d3.scaleOrdinal().range([])

【讨论】:

  • 谢谢。我不经常使用这种组合,并且在您在这里回答三年后才看到变化,当我在自己的工作中想知道为什么这不再起作用时!作为回应,我已经编辑了我的原始答案。
【解决方案4】:

Peter Ellis 的回答可以完成这项工作,但这是一种替代方法,恕我直言,它更简洁且更易于理解......

(另外,应该注意的是,节点可以同时在sourcetarget 向量中,在这种情况下,根据您的规范,它们应该是哪种颜色是不确定的。)

library(networkD3)

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)

# make a nodes data frame out of all unique nodes in networkData
nodes <- data.frame(name = unique(c(networkData$src, networkData$target)))

# make a group variable where nodes in networkData$src are identified
nodes$group <- nodes$name %in% networkData$src

# make a links data frame using the indexes (0-based) of nodes in 'nodes'
links <- data.frame(source = match(networkData$src, nodes$name) - 1,
                    target = match(networkData$target, nodes$name) - 1)

forceNetwork(Links = links, Nodes = nodes, Source = "source",
             Target = "target", NodeID ="name", Group = "group",
             opacity = 1, opacityNoHover = 1)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-07-11
    • 2017-01-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多