从网络边缘排斥文本

时间:2019-04-01 22:27:38

标签: r visualization graph-visualization ggrepel ggraph

绘制网络时,如果节点的标签还可以避开网络边缘,那将是很好的选择。例如。在下面的示例中,可以将所有标签移到网络外部。我已经尝试了几个软件包,但是到目前为止,还没有找到一种可行的方法。有办法吗?下面的示例:

library(ggraph)
library(tidygraph)
reprex <- tibble(to = sample(1:10, 100,replace=T),
                 from = sample(1:10, 100,replace=T)
                 ) %>%
  as_tbl_graph()
V(reprex)$label1 <- rep("label",10)

reprex_plot <- reprex %>%
  ggraph() +
  geom_node_point() +
  geom_edge_link(color="grey")+
  geom_node_text(aes(label=label1),repel=T,force=100)+
  theme_bw()

reprex_plot

enter image description here

1 个答案:

答案 0 :(得分:1)

据我了解的问题,ggrepelgeom_node_text使用的程序包,只能访问节点所在的层,而不能“看到”边缘。这使得ggrepel不太适合用于网络(或者我缺少某些东西)。

不幸的是,尽管我已经寻找了一段时间,但对于这个问题我也没有一个很好的解决方案。以下是两个建议,您(或任何人)如何朝着使用ggraph()的更好的标记方式迈进:

1:将文本作为节点

所以我的一个主意是让网络布局算法为我们完成工作。我制作了另一组仅包含标签的节点。标签节点仅连接到它们所标签的网络中的一个相应节点。我们开始:

library(dplyr)
library(ggraph)
library(tidygraph)

set.seed(123)

reprex <- tibble(from = sample(1:10, 100, replace = TRUE),
                 to = sample(1:10, 100, replace = TRUE)) %>%
  as_tbl_graph() %>% 
  activate(edges) %>% 
  mutate(color = "grey")

我在此处添加灰色的边缘颜色,因为在最终绘图中我们将使用两种不同的颜色。

nodes <- reprex %>% 
  activate(nodes) %>% 
  as_tibble() # extract data.frame of nodes

# create new graph with just the lables
labels <- tibble(from = 1:10,
                 to = 11:20) %>% 
  as_tbl_graph() %>% 
  activate(nodes) %>% 
  mutate(label1 = "label",
         is_label = !name %in% nodes$name) %>% 
  activate(edges) %>% 
  mutate(color = "black")

# join graph and labels
new_graph <- graph_join(labels, reprex, by = "name")

现在我们有了带有标签节点的新图形,我们可以进行绘制。请注意,我在新图中添加了变量is_label,以便我们可以使用不同的节点形状并确保仅标记了标签节点:

reprex_plot <- new_graph %>% 
  ggraph() +
  geom_edge_link(aes(color = color)) +
  geom_node_point(aes(filter = !is_label, shape = "circle"), show.legend = FALSE) +
  scale_edge_color_identity() +
  geom_node_text(aes(filter = is_label, label = label1), hjust = -0.1) +
  theme_void()
reprex_plot

enter image description here

很明显,还有很多改进的余地。标签现在离节点很远。它们仍然与自己的边缘重叠(尽管我认为可以通过提供更好的平衡值来解决)。尽管这在自动布局中效果很好,但其他布局可能会做一些奇怪的事情,具体取决于您的数据。我真的希望其他人能提出更好的解决方案。但是我想我最好把它放在这里。也许有人感到鼓舞。

2:标签代替文本

解决该问题的另一种方法是在文本上使用白色背景。该解决方案的灵感来自用于网络绘图的GUI程序如何处理该问题。我们可以使用ggplot2的{​​{1}},尽管geom_label可以达到相同的目的。该解决方案简单得多,但也有局限性。这是整个事情的总汇:

geom_node_label()

enter image description here

我删除了标签上的边框,并将其直接放在其节点(tibble(from = sample(1:10, 100, replace = TRUE), to = sample(1:10, 100, replace = TRUE)) %>% as_tbl_graph() %>% activate(nodes) %>% mutate(label1 = "label") %>% ggraph() + geom_edge_link(color = "grey") + geom_node_point() + geom_label(aes(x = x, y = y, label = label1), nudge_y = 0.1, label.size = NA) + theme_void() )上方。根据图的大小,结果可能会有所不同,因此您可能需要更改该值。

在较大的网络上,标签的白框可能会掩盖其他节点。