R networkD3 包:在 simpleNetwork() 中对节点进行着色

13

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

# 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() 中似乎不支持这个功能(但我希望有人能帮助我用自制脚本实现):

enter image description here

类似但不相关的问题已经在这里提出。


2
在同一套包中使用 forceNetwork() 是否可以?您可以通过 Group 和 JavaScript 比例控制颜色。如果您有兴趣,我可以提供完整的答案。 - Peter Ellis
@PeterEllis 是的,那将非常有帮助。 - warship
可能有一个相关的问题,其中必须使用预先指定的颜色对节点进行着色:http://stackoverflow.com/questions/38793947/r-colouring-scheme-in-networkd3-vs-igraph?noredirect=1#comment65115769_38793947 - johnny utah
4个回答

14

以下是如何使用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))

输入图像描述


3
节点全部标记上标签会很好。您能否详细说明如何使节点(对于“src”和“target”)的名称自动显示,而不仅仅是在悬停时可访问性? - warship
1
这里有一个名为 opacityNoHover 的参数。使用 opacityNoHover = 1 来始终显示节点标签。 - Dale Kube

5

Peter Ellis之前的回答可能曾经有效,但是在新版本中代码已经更新。现在你需要使用d3.scaleOrdinal().range([])而不是d3.scale.ordinal().range([])


2
谢谢。我很少使用这种组合,直到在自己的工作中想知道为什么这不再起作用时,才在您的答案三年后看到了更改!我已经做出了回应并编辑了我的原始答案。 - Peter Ellis

2

Peter Ellis的回答可以解决问题,但这是一种备选方法,我认为它更加简洁易懂...

(另外,需要注意的是,节点可以同时出现在“源”和“目标”向量中,这种情况下,根据您的规定应该给它们什么颜色是不确定的。)

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)

enter image description here


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

enter image description here


非常酷。我确信你能在 networkD3 中找到类似的东西 :-) +1 - warship

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