从网络边缘排斥文本 [英] Repel text from edges in network

查看:27
本文介绍了从网络边缘排斥文本的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在绘制网络时,如果节点的标签也可以避开网络边缘,那就太好了.例如.在下面的示例中,可以将所有标签移到网络之外.我已经尝试了几个软件包,但到目前为止还没有找到一种黑客方法来做到这一点.有办法吗?下面的例子:

When drawing a network, it would be nice if the labels of the nodes could also avoid network edges. E.g. in the example below, it would be possible to move all the labels outside the network. I've tried several packages, but so far have not found even a hacky way to do that. Is there a way? Example below:

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

推荐答案

据我了解这里的问题,ggrepel,也就是geom_node_text使用的包,只能访问节点所在的层,而不能看到"边缘.这使得 ggrepel 不太适合网络(或者我遗漏了一些东西).

As far as I understand the problem here, ggrepel, which is the package used by geom_node_text, only has access to the layer on which the nodes are and does not 'see' the edges. This makes ggrepel not very suitable for networks (or I'm missing something).

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

Unfortunately, I don't have a very good solution for this problem either, although I have been looking for one for a while now. Here are two suggestions how you (or anyone) could move towards a better way of labeling with ggraph():

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

So one idea I had was to let the network layout algorithm do the work for us. I make another set of nodes that contain only the labels. The label nodes are only connected to the one respective node in network they label. Here we go:

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

我在这里添加了边缘颜色灰色,因为在最终图中我们将有两种不同的颜色.

I add the edge color grey here since we will have two different colors in the final plot.

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,因此我们可以使用不同的节点形状并确保仅标记标签节点:

Now that we have the new graph with label nodes, we can plot. Note, that I added a variable is_label to the new graph so we can use different node shapes and make sure only the label nodes are labeled:

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

显然,还有很大的改进空间.标签现在离节点很远.它们仍然与它们自己的边缘重叠(尽管我认为可以通过提供更好的 hjust 值来解决这个问题).虽然这适用于自动布局,但其他布局可能会做一些奇怪的事情,具体取决于您的数据.我真的希望其他人提出更好的解决方案.但我想我不妨把它放在这里.也许有人觉得受到启发.

Clearly, there is A LOT of room for improvement. The labels are now very far away from the nodes. They still overlap with their own edges (though that could be solved by providing better hjust values, I think). And while this works well with the auto layout, other layouts might do strange things, depending on your data. I really hope someone else comes up with a better solution. But I thought I might as well put it out here. Maybe someone feels inspired.

另一种解决问题的方法是在文本上使用白色背景.该解决方案的灵感来自于用于网络绘图的 GUI 程序如何处理该问题.我们可以使用 ggplot2geom_label 来实现这一点,尽管 geom_node_label() 也能做到这一点.这个解决方案要简单得多,但也有局限性.这是一个管道中的全部内容:

Another way to get around the problem is to use white background on the text. This solution is inspired by how GUI programs for network plotting handle the problem. We can use ggplot2's geom_label for this, although geom_node_label() would accomplish the same. This solution is a lot more straightforward, but also limited. Here is the whole thing in one pipe:

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

我移除了标签上的边框并将它们直接放置在它们的节点上方(nudge_y = 0.1).您的结果可能因绘图的大小而异,因此您可能需要更改该值.

I removed the border on the labels and placed them directly above their nodes (nudge_y = 0.1). Your results may differ depending on the size of the plot so you might need to change that value.

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

On larger networks, the white boxes of the labels might cover up other nodes.

这篇关于从网络边缘排斥文本的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆