Наложение субплота ggraph

Мне нужно наложить набор вспомогательных участков на графике. Каждый график соответствует конкретному узлу, поэтому они должны быть размещены с использованием координат каждого узла. Следующий код создает график и набор вспомогательных участков для наложения.

 # Create the graph
 library(data.table)
 library(igraph)
 library(ggraph)

 mydata <- data.table(from=c("John", "John", "Jim"), to=c("John", "Jim", "Jack"))
 graph <- graph_from_data_frame(mydata)
 V(graph)$class <- c("John", "Jim", "Jack")

 ggraph(graph, layout = 'linear') + 
 geom_edge_link() + 
 geom_node_point() +
 geom_node_text(aes(label = class))

 # Plots to overlay
 John <- ggplot(diamonds, aes(carat)) + geom_histogram(fill = "red") + 
 ggtitle("John")
 Jim <- ggplot(diamonds, aes(depth)) + geom_histogram(fill = "blue") + 
 ggtitle("Jim")
 Jack <- ggplot(diamonds, aes(price)) + geom_histogram(fill = "green") + 
 ggtitle("Jack")

Следующее изображение иллюстрирует фактический и желаемый результат.

1 ответ

Решение

Ты можешь использовать ggraph::create_layout чтобы извлечь координаты х и у узлов, а затем использовать purrr::pmap применять ggplot2::annotation_custom к каждому из ваших участков.

library(purrr)
library(ggplot2)
library(igraph)
library(ggraph)

# Your code, mostly unchanged (removed data.table)
mydata <- data.frame(from=c("John", "John", "Jim"), to=c("John", "Jim", "Jack"))
graph <- graph_from_data_frame(mydata)
V(graph)$class <- c("John", "Jim", "Jack")


John <- ggplot(diamonds, aes(carat)) + geom_histogram(fill = "red") + 
  ggtitle("John")
Jim <- ggplot(diamonds, aes(depth)) + geom_histogram(fill = "blue") + 
  ggtitle("Jim")
Jack <- ggplot(diamonds, aes(price)) + geom_histogram(fill = "green") + 
  ggtitle("Jack")

# New code
graph_df <- create_layout(graph, layout = 'linear')

graph_df это фрейм данных с содержимым:

  x y name class ggraph.orig_index circular ggraph.index
1 1 0 John  John                 1    FALSE            1
2 2 0  Jim   Jim                 2    FALSE            2
3 3 0 Jack  Jack                 3    FALSE            3

Ты можешь позвонить ggraph(graph_df) непосредственно; под капотом ggraph(graph) делал те же шаги.


Теперь мы создаем вложенный список, где первый элемент - это список объектов ggplot, которые мы хотим использовать для вставок (убедитесь, что они в правильном порядке относительно их порядка в graph_df). Второй элемент - это список координат x, а третий элемент - список координат y. Затем мы применяем функцию, которая создает grobs для вставки, используя координаты x и y, чтобы определить поле, куда он пойдет в конечном графике.

grobs <- pmap(.l = list(plots = list(John, Jim, Jack), 
                        x = as.list(graph_df$x), 
                        y = as.list(graph_df$y)),

              .f = function(plots, x, y) {

    annotation_custom(grob = ggplotGrob(plots + theme_grey(base_size = 4)),
                      xmin = x - .25, xmax = x + .25,
                      ymin = y + .1,  ymax = y + .6)
  })

Тогда вашему коду сверху просто нужно добавить этот объект и немного поиграть с ограничениями:

ggraph(graph_df) + 
  geom_edge_link() + 
  geom_node_point() +
  geom_node_text(aes(label = class)) + 
  expand_limits(x = c(0.5,3.5)) +
  coord_equal() +
  grobs

Некоторые заметки:

  • Построение врезных графиков также может быть выполнено программно с использованием purrr функции.
  • base_size = Аргумент в функции, которую мы создали, нужно будет по вкусу.
  • Смещения для x и y в функции также должны быть выполнены вручную, исходя из диапазона координат в вашем реальном графике.
Другие вопросы по тегам