library(tidyverse)
library(ggraph)
library(igraph)
library(gridExtra)
library(readxl)
<- read_excel("./genji.xlsx")
genji
<- graph_from_data_frame(genji)
genji_g
<- c('#FF1E00',
cols '#FF7F00',
'#04819E',
'#00BF32',
'#5F4690FF',
'#CDC8B1')
Любовные сети блистательного принца. Часть 2. Клубок семейных отношений.
Учебный проект по построению сетей на примере романа Мурасаки Сикибу Гэндзи-моногатари
Бывает начало - но нет конца
Данная работа продолжает и логично вытекает из предыдущей по визуализации сетей. Вспомнить её можно, нажав здесь. Там же я описывал то, как собирал датасет. Вкратце расскажу вновь. Я использовал печатное издание романа “Повесть о Гэндзи” в переводе Т.Л. Соколовой-Делюсиной для подсчета совместной в главах встречаемости основных персонажей. Из нового: дополнил датасет новыми строками и ввёл новый вид связи - “родитель-ребёнок”, чтобы отличить от просто семьи (связь между братьями-сестрами). Теперь цель посмотреть на визуализации не только любовные (романтические) сети, но и родственные. Роман повестует о дворцовой жизни высшей аристократии японского общества периода Хэйан. Интересно, насколько запутан “клубок семейных отношений”. Обновленный датасет доступен в репозитории на гитхабе.
Приступаем к работе. Построение графа.
Подгружаем необходимые библиотеки датасет в формате xlsx. При помощи функции graph_from_data_frame() создаем объект класса iGraph. Поскольку у нас теперь 6 видов связи (нейтральное, родитель-ребенок, романтические отношения, семья, противник, ложное родство) добавляем в палитру ещё один цвет.
Добавим дополнительный аттрибут вершине - центральность по степени. Другими словами, определим с каким количеством других узлов связан данный, и добавим в качестве аттрибута.
<- degree(genji_g)
degrees <- genji_g %>%
genji_g set.vertex.attribute('degree', value = degrees)
Теперь посмотрим на характеристики получившегося объекта типа iGraph.
Граф направленный, именнованный, взвешенный. Содержит 49 узлов и 104 ребра.
Вершина графа - один из персонажей романа (имя персонажа - атрибут ‘name’). О степени я говорил выше.
Ребро - упоминание в рамках одной главы. Ребро обладает атрибутами ‘weight’, который показывает в скольких главах персонажи упоминаются, и ‘relationship’, который указывает характер связи между персонажами романа.
edge_density(genji_g ) #Считаем плотность сети
components(genji_g )$csize #Смотрим на входящие компоненты
<- largest_component(genji_g) #Определим наиболее удаленные друг от друга узлы и узнаем расстояние между ними
lgc farthest_vertices(lgc)
transitivity(genji_g ) #Смотрим транзитивность
Плотность сети составляет 0.04421769. В графе одна компонента, включающая 49 вершин. При попытке измерить наибольшее расстояние между узлами “машина” привела пару “принц Гэндзи - госпожа Мурасаки”. Алгоритм нашел наибольшее возможное расстояние в 30 ребер между ними, хотя узлы напрямую также связаны (если честно, не могу понять почему). Транзитивность равна 0.1695554.
Строим граф. Как я выяснил в своей предыдущей работе, для моих данных подходит укладка “dh”. Размер узла задается атрибутом ‘degree’. Чтобы визуально не засорять граф, фильтрую подписи к тексту degree > 1.
set.seed(21032025)
ggraph(genji_g, layout = "dh", maxiter = 500) +
scale_fill_manual(values = cols) +
geom_edge_link(aes(width = weight, color = relationship), alpha = .25,
show.legend = TRUE) +
geom_node_point(aes(size = degree),
shape = 1,
show.legend = FALSE) +
geom_node_text(aes(filter = (degree > 1),
label = name),
repel = TRUE) +
theme_graph()
Подграфы определенных персонажей
Для начала воспользуемся функцией make_ego_graph(). Мне интересно посмотреть на “друзья друзей” двух персонажей романа: То-но тюдзё и госпожи Мурасаки.
То-но тюдзё - брат первой жены принца Гэндзи, сын Левого министра (а в конце-середине роман сам стал Левым министром). Это один из главных персонажей романа. Если мы посмотрим на получившийся выше граф, то увидим, что он вокруг себя как бы формирует отдельный клубок связей.
Госпожа Мурасаки, вторая жена принца Гэндзи, хоть не такая активная в плане социальных связей как То-но тюдзё, но важнейший персонаж романа. Недаром согласно некоторым исследователям “Гэндзи моногатари” в момент написания именовался как “Мурасаки моногатари”.
И там, и там буду использовать order = 1 по одной простой причине: принц Гэндзи, как главный герой, связан почти со всеми персонажами романа. При order = 2 получим схожий граф, что и выше (за исключением трех вершин; об этом ниже).
Подграф для То-но тюдзё
<- make_ego_graph(
to_no_tyudzyo
genji_g,order = 1,
nodes = "То-но тюдзё (сын Левого министра)",
mode = "all"
1]]
)[[
set.seed(21032025)
ggraph(to_no_tyudzyo, layout = "dh", maxiter = 500) +
scale_fill_manual(values = cols) +
geom_edge_link(aes(width = weight, color = relationship), alpha = .25,
show.legend = TRUE) +
geom_node_point(aes(size = degree),
shape = 1,
show.legend = FALSE) +
geom_node_text(aes(label = name),
repel = TRUE) +
theme_graph()
Цвета связи поменялись по сравнению с предыдущим графом (возможно, из-за того, что не все виды связей представлены + я не делал привязки цвет-связь). Однако, можно увидеть, как желтым веером отходят от То-но тюдзё ребра с типом связи “родитель-ребёнок”, т.е. у него была большая семья (преимущественно дети), которые потом тесно взаимодействовали с другими персонажами романа.
Делаем то же самое для госпожи Мурасаки
<- make_ego_graph(
murasaki
genji_g,order = 1,
nodes = "Госпожа Мурасаки",
mode = "all"
1]]
)[[
set.seed(21032025)
ggraph(murasaki, layout = "dh", maxiter = 500) +
scale_fill_manual(values = cols) +
geom_edge_link(aes(width = weight, color = relationship), alpha = .25,
show.legend = TRUE) +
geom_node_point(aes(size = degree),
shape = 1,
show.legend = FALSE) +
geom_node_text(aes(label = name),
repel = TRUE) +
theme_graph()
Госпожа Мурасаки тесно связано только с принцем Гэндзи и со своим отцом принц Сикибукё. С одной стороны, это указывает на судьбы госпожи, которая после смерти матери стала воспитанницей, а затем и женой принца Гэндзи. С другой стороны, демонстрирует, что у неё не было детей (при этом она оставалась любимейшей женой).
Наверху я написал, что 3 вершины не будут обнаружены. Почему? Это результат подсчета точек сочленения.
articulation_points(genji_g)
Функция нам выдает 4 узла: госпожа Макибасира, юная госпожа Акаси, госпожа Ханатирусато и принц Гэндзи. Госпожа Макибасира и юная госпожа Акаси связаны романтическим отношениями с юношами, напрямую никак не пересекающихся с принцем Гэндзи. У госпожи Ханатирусато упоминается мать (тоже не связана с Гэндзи).
Можно также подсчитать клики.
clique_num(genji_g)
cliques(genji_g, min=5)
И при распечатывании он будет выдавать родственные связи:
[[1]] + 5/49 vertices, named, from 3c1c9aa: [1] принц Гэндзи То-но тюдзё (сын Левого министра) [3] Утюдзё (Касиваги) Госпожа Оми
[5] Бэн-но сёсё
[[2]] + 5/49 vertices, named, from 3c1c9aa: [1] принц Гэндзи То-но тюдзё (сын Левого министра) [3] Утюдзё (Касиваги) Госпожа Оми
[5] Госпожа Тамакадзура
[[3]] + 5/49 vertices, named, from 3c1c9aa: [1] принц Гэндзи То-но тюдзё (сын Левого министра) [3] Утюдзё (Касиваги) Госпожа Оми
[5] Госпожа Кумои-но кари
[[4]] + 5/49 vertices, named, from 3c1c9aa: [1] принц Гэндзи То-но тюдзё (сын Левого министра) [3] Утюдзё (Касиваги) Госпожа Оми
[5] Госпожа Кокидэн
Во всех упомянут принц Гэндзи, То-но тюдзё и дети последнего.
Обнаружение сообществ
Посчитаем модулярность. Модулярность - это одна из мер структуры сетей или графов для измерения силы разбиения сети на модули. В качестве варианта разберем кейс с полом. Можно ли поделить граф на два сообщества по полу: мужской и женский. Для этого создаем отдельный атрибут у вершины ‘gender’.
<- genji_g %>%
genji_g set.vertex.attribute('gender', value = case_when(
str_detect(V(genji_g)$name, "(оспожа|наложница|Гэн-найси|Дама|Нокиба-но|монахиня)") ~ "1",
.default = "2"))
<- as.numeric(V(genji_g)$gender)
gender modularity(genji_g, gender)
Модулярность равна 0.005177515, иначе говоря, по полу разделить не получится.
Попробуем алгоритм “случайного блуждения”.
<- cluster_walktrap(genji_g)
cw
par(mar = rep(0, 4))
plot(cw, genji_g, edge.arrow.size = 0,
vertex.size = 2, vertex.color = "plum",
vertex.label.dist = 1,
edge.curved = 0.2,
edge.color = "grey80")
modularity(cw)
Модулярность составила уже 0.1381639. Но все равно мало. Многие моменты не могу перевести с “машинного” на человеческий. Правда, есть 3 небольшие четко выделенных сообщества: на крсаном фоне-подложке - семья Правого министра, на желтом - семья бывшего управителя провинции Харима (Акаси), на светло-зеленом - Адзэти-но дайнагон и наложница Кирицубо (отец и дочь). В остальных случаях - интерпретация вызывает трудности.
Попробуем другой алгоритм - “главный собственный вектор”.
<- cluster_leading_eigen(genji_g)
cev
par(mar = rep(0, 4))
plot(cev, genji_g, edge.arrow.size = 0,
vertex.size = 2, vertex.color = "plum",
vertex.label.dist = 1,
edge.curved = 0.2,
edge.color = "grey80")
modularity(cev)
Модулярность составила 0.1960885. Здесь уже можно хоть что-то разобрать. Голубая область объединяет родственников Гэндзи и дворцовых служителей периода его раннего детства. Жёлтый - основные персонажи, часто появляющиеся на страницах книги. Фиолетовый потомки (дети и внуки) То-но тюдзё. Красный - основные представители дворцовой жизни.
Распутывая семейный клубок…
Родственные связи среди персонажей очень сильны. В той или иной мере это раскрывалось почти в каждом пункте. Даже в примере эго-графа госпожи Мурасаки упоминается родственная связь типа “родитель - ребёнок”. Оно показывает не только на закрытость приближенных ко двору семейств (глубоко переплетены по сути несколько семей: императорская, Правого министра, Левого министра и непосредственно Гэндзи), но и на то значение, которое им придавали во времена написания романа. Считалось, что происхождение намного важнее, чем ум или талант, потому что энергия имеет свойство накапливаться в роду. Если твой отец был хорошим чиновником, то и ты должен быть хорошим чиновником. А если ты из отдаленной провинции - то нечего делать в столице. Вся эта история с построением графа по “Гэндзи моногатари” лишний раз показывает, что необходимо знать атмосферу и контекст эпохи (а для кого-то изучать генеалогии).