如何控制ggraph中的节点颜色?

How to control node color in ggraph?

我有一个网络图,我想给边着色以匹配它们各自的节点。这在 igraph 情节中相当直接,但我更愿意在 ggraph 中这样做,因为我喜欢该包提供的其他美学。

ggraph 中似乎无法控制节点颜色;而边缘颜色被广泛覆盖。

我的问题是:如何将我的边与使用自定义函数着色的节点相匹配,以便 'leaves' 节点的每条边都与其节点着色相同。这应该可以帮助人们更轻松地跟踪网络中的流程。一个更普遍的问题是:ggraph 如何在美学论证之外分配颜色。我的问题类似于我之前在这里问过的另一个问题,但反过来(将边与节点匹配),发现

这是一个可重现的例子:

library(tidyverse)
library(igraph)
library(ggraph)
library(tidygraph)
library(RColorBrewer)

## the custom function using Color Brewer
cols_f <- colorRampPalette(RColorBrewer::brewer.pal(11, 'Spectral'))

## make the graph
g <- erdos.renyi.game(50, .1) 

# provide some names
V(g)$name <- 1:vcount(g)

#plot using ggraph
g %>% 
  as_tbl_graph() %>% 
  activate(nodes) %>% 
  mutate(degree  = centrality_degree()) %>% 
  ggraph()+
  geom_edge_fan(aes(color = as.factor(from),
                    alpha = ..index..),
                show.legend = F)+
  geom_node_point(aes(size = degree), 
                  color = cols_f(vcount(g)), # custom function for node color
                  show.legend = F)+
  scale_color_manual(values = cols_f(ecount(g)))+ # custom function for edge color
  coord_equal()

我个人发现明确使用 layout 对象有助于理解变量映射。

它有 类 "layout_igraph"+"layout_ggraph"+"data.frame" 并且包含

  1. a data.frame 用于坐标由 create_layout
  2. 定义的节点
  3. 输入"tbl_graph"+"igraph"对象(参见attributes(layout)$graph

前者由geom_node_point访问绘制节点,后者由geom_edge_fan绘制边

节点的颜色可以用 ggplot2 标准 scale_color_manual 控制,边的颜色可以用 ggraph 添加 scale_edge_color_manual。如果相应地设置 limits 属性,则两者都可以与相同的节点名称~颜色映射一起使用,因为它包含...

a character vector that defines possible values of the scale and their order.


library(tidyverse)
library(igraph)
library(ggraph)
library(tidygraph)

## the custom function using Color Brewer
cols_f <- colorRampPalette(RColorBrewer::brewer.pal(11, 'Spectral'))

## make the graph
g <- erdos.renyi.game(50, .1) 

# provide some names
V(g)$name <- 1:vcount(g)

# plot using ggraph
graph_tbl <- g %>% 
  as_tbl_graph() %>% 
  activate(nodes) %>% 
  mutate(degree  = centrality_degree()) 

layout <- create_layout(graph_tbl, layout = 'igraph', algorithm = 'nicely')

ggraph(layout) +
  geom_edge_fan(
    aes(color = as.factor(from), alpha = ..index..),
    show.legend = F
  ) +
  geom_node_point(
    aes(size = degree, color = as.factor(name)),
    show.legend = F
  ) +
  scale_color_manual(
    limits = as.factor(layout$name),
    values = cols_f(nrow(layout))
  ) +
  scale_edge_color_manual(
    limits = as.factor(layout$name),
    values = cols_f(nrow(layout))
  ) +
  coord_equal()

我已经学会了如何做到这一点。它实际上非常简单,并且利用了 tidygraph,我建议将其用于图形分析。它是为与 ggraph 配对而编写的,因此有助于实现良好的工作流程。

基本上,您想在 fromto 列上将 node 数据与 edge 数据合并 - 取决于您想要边缘的节点匹配到。

下面是执行此操作的一些代码。

# same as original code above
library(tidyverse)
library(igraph)
library(ggraph)
library(tidygraph)
library(RColorBrewer)

## the custom function using Color Brewer
cols_f <- colorRampPalette(RColorBrewer::brewer.pal(11, 'Spectral'))

## make the graph
g <- erdos.renyi.game(50, .1) 

# provide some names
V(g)$name <- 1:vcount(g)


# Here's the new parts

#create random categories to the nodes
V(g)$category <- sample(LETTERS, vcount(g), T)


# turn igraph into tbl_graph (still igraph under the hood!)
g_tbl <- as_tbl_graph(g)


# create new tibble from nodes with a variable from to merge with edges
node_from <- g_tbl %>%
    as_tibble() %>%
    mutate(from = row_number())


# merge with edges on the new 'from' variable

new_g_tbl <- g_tbl %>%
    activate(edges) %>%
    left_join(node_from) 

# plot
new_g_tbl %>%
    ggraph() +
    geom_edge_arc(
        aes(color = category),
        end_cap = circle(2.5, 'mm'),
        arrow = arrow(length =
                          unit(2.5,
                               'mm'),
                      type = 'closed'),
        strength = 0.1,
        show.legend = F
    ) +
    geom_node_point(aes(color = category),
                    show.legend = F)