Отталкивать текст от краев в сети

При рисовании сети было бы неплохо, если бы метки узлов также избегали границ сети. Например. в приведенном ниже примере можно было бы переместить все метки за пределы сети. Я пробовал несколько пакетов, но пока не нашел даже хитроумного способа сделать это. Есть способ? Пример ниже:

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

введите описание изображения здесь


person puslet88    schedule 01.04.2019    source источник


Ответы (1)


Насколько я понимаю здесь проблема, ggrepel, который является пакетом, используемым geom_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

введите здесь описание изображения

Ясно, что есть ОЧЕНЬ возможности для улучшения. Метки теперь очень далеко от узлов. Они по-прежнему перекрываются своими собственными краями (хотя, я думаю, это можно решить, предоставив лучшие значения hjust). И хотя это хорошо работает с автоматическим макетом, другие макеты могут делать странные вещи в зависимости от ваших данных. Я очень надеюсь, что кто-то другой найдет лучшее решение. Но я подумал, что можно было бы выложить это здесь. Может, кто-то почувствует вдохновение.

2: метки вместо текста

Другой способ обойти проблему - использовать белый фон для текста. Это решение основано на том, как программы с графическим интерфейсом для построения сетевых графиков решают эту проблему. Мы можем использовать для этого geom_label ggplot2, хотя geom_node_label() добьется того же. Это решение намного более простое, но также ограниченное. Вот все это в одной трубе:

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). Ваши результаты могут отличаться в зависимости от размера графика, поэтому вам может потребоваться изменить это значение.

В более крупных сетях белые прямоугольники меток могут закрывать другие узлы.

person JBGruber    schedule 02.04.2019