Отталкивать текст от краев в сети - PullRequest
7 голосов
/ 02 апреля 2019

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

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 Ответ

1 голос
/ 02 апреля 2019

Насколько я понимаю, здесь проблема, 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

enter image description here

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

2: надписи вместо текста

Еще один способ обойти проблему - использовать белый фон для текста.Это решение основано на том, как программы с графическим интерфейсом для построения сетей решают эту проблему.Для этого мы можем использовать ggplot2 1031 *, хотя 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()

enter image description here

Я убрал границу на метках и поместил их прямо над их узлами (nudge_y = 0.1).Ваши результаты могут отличаться в зависимости от размера графика, поэтому вам может потребоваться изменить это значение.

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

...