В этом уроке мы научимся работать с пакетом ggraph, который позволяет контролировать внешний вид всех элементов графа: узлов, ребер, фона, подписей, а также позволяет управлять раскладкой сети в целом. Мы также попробуем наложить одну из сетей на карту, чтобы отразить характер пространственных связей.
В качестве основы мы возьмем небольшой датасет “Тюдоды” из пакета historydata.
Warning: package 'ggplot2' was built under R version 4.5.2
Warning: package 'readr' was built under R version 4.5.2
library(ggraph)library(igraph)
tudors <- tudorstudors
Преобразуем таблицу в объект igraph.
tudors_g <-graph_from_data_frame(tudors)tudors_g
IGRAPH e72c39b DN-- 25 35 --
+ attr: name (v/c), relationship (e/c)
+ edges from e72c39b (vertex names):
[1] Henry VII ->Elizabeth of York
[2] Arthur Tudor ->Catharine of Aragon
[3] Henry VIII ->Catharine of Aragon
[4] Henry VIII ->Anne Boleyn
[5] Henry VIII ->Jane Seymour
[6] Henry VIII ->Anne of Cleves
[7] Henry VIII ->Katherine Howard
[8] Henry VIII ->Catherine Parr
+ ... omitted several edges
19.1 Дизайн узлов
Для визуализации используем библиотеку ggraph. Минимум необходимых усилий уже даст нам что-то осмысленное, но это только начало.
При работе с узлами мы можем закодировать несколько переменных при помощи размера, цвета или, например, формы. Здесь мы ограничимся двумя способами: при помощи размера отразим степень узла (количество связей с другими участниками), а при помощи цвета – гендер.
Для этого сначала считаем степень узлов; как это делать, мы обсуждали в предыдущем уроке.
d <-as.numeric(degree(tudors_g))V(tudors_g)$degree <- dtudors_g
IGRAPH e72c39b DN-- 25 35 --
+ attr: name (v/c), degree (v/n), relationship (e/c)
+ edges from e72c39b (vertex names):
[1] Henry VII ->Elizabeth of York
[2] Arthur Tudor ->Catharine of Aragon
[3] Henry VIII ->Catharine of Aragon
[4] Henry VIII ->Anne Boleyn
[5] Henry VIII ->Jane Seymour
[6] Henry VIII ->Anne of Cleves
[7] Henry VIII ->Katherine Howard
[8] Henry VIII ->Catherine Parr
+ ... omitted several edges
Наш граф носит направленный характер, а значит мы можем отразить и направленность, и характер связей. Кодируем атрибут relationship, например, типом линии.
set.seed(21092024)# добавляем итерации для укладкиggraph(tudors_g, layout ="dh", maxiter =100) +# вот тут вносим измененияgeom_edge_link(aes(edge_linetype = relationship),# меняем цвет линииcolor ="grey50",# меняем тип линииedge_width =1.2) +geom_node_point(aes(size = degree, fill = gender),shape =21, color ="black" ) +#geom_node_text(aes(label = name)) +#scale_fill_manual(values = cols) +scale_size(guide ='none') +theme_graph(base_family ="sans") +# перемещаем легендуtheme(legend.position ="bottom")
Можно заменить линии на стрелки.
set.seed(21092024)ggraph(tudors_g, layout ="dh", maxiter =100) +geom_edge_link(color ="grey50",# стрелкаarrow =arrow(angle =30, length =unit(0.25, "cm"),ends ="last", type ="closed"),# небольшой отступ от кружкаend_cap =circle(1.5, "mm") ) +geom_node_point(aes(size = degree, fill = gender),shape =21, color ="black" ) +#geom_node_text(aes(label = name)) +scale_fill_manual(values = cols) +scale_size(guide ='none') +theme_graph(base_family ="sans") +theme(legend.position ="bottom")
Или придать им изогнутости и раскрасить.
set.seed(21092024)ggraph(tudors_g, layout ="dh", maxiter =100) +# вот тут измененияgeom_edge_arc(aes(color = relationship),# как сильно изгибатьstrength =0.2,arrow =arrow(angle =30, length =unit(0.2, "cm"),# от родителей к детям, а не наоборотends ="first", type ="closed"),# тут тоже меняем start_cap =circle(1.5, "mm") ) +geom_node_point(aes(size = degree, fill = gender),shape =21, color ="black" ) +#geom_node_text(aes(label = name)) +scale_fill_manual(values = cols) +# цветовая шкала для реберscale_edge_color_manual(values = cols) +scale_size(guide ='none') +theme_graph(base_family ="sans") +theme(legend.position ="bottom")
19.5 Подписи с geom_node_label()
Если мы просто вернем подписи, то они будут не очень читаемы, даже на нашем (очень небольшом) датасете.
set.seed(21092024)ggraph(tudors_g, layout ="dh", maxiter =100) +# тип линии вместо цвета, убираем стрелкуgeom_edge_arc(aes(linetype = relationship),color ="grey50",strength =0.2 ) +geom_node_point(aes(size = degree, fill = gender),shape =21, color ="black" ) +# чуть подвинемgeom_node_text(aes(label = name), nudge_y =0.5) +scale_fill_manual(values = cols) +# тип линии для реберscale_edge_linetype_manual(values =c("dashed", "solid")) +scale_size(guide ='none') +theme_graph(base_family ="sans") +theme(legend.position ="bottom")
visOptions(tudors_3d, highlightNearest =list(enabled =TRUE, degree =1, hover =TRUE), nodesIdSelection =FALSE) |>visPhysics(maxVelocity =20, stabilization =FALSE) |>visInteraction(dragNodes =TRUE) |># удалите эту строку, если хотите видеть граф во вьюереvisSave(file ="tudors.html")
Et voilà. Все наши Тюдоры как живые.
19.8 Возможности VisNetwork
Подробнее о возможностях visNetwork можно почитать здесь. Вот так можно добавить всплывающие подсказки и иконки для узлов.
library(visNetwork)# Создаем узлы с tooltipsnodes <-data.frame(id =1:3, label =c("King", "Queen", "Prince"), # иконкиshape ="icon", # tooltips для каждого узлаtitle =c("The ruler of the kingdom", "The queen of the land", "The prince in the castle"), icon =list(face ="FontAwesome",# коды иконок FAcode =c("f118", "f005", "f183"), size =50,color =c("darkred", "purple", "blue") # Цвета иконок ))# связи между узламиedges <-data.frame(from =c(1, 1), to =c(2, 3))# граф с иконками и tooltipsvisNetwork(nodes, edges) |>visOptions(highlightNearest =list(enabled =TRUE, degree =1, hover =TRUE)) |>addFontAwesome()