library(ggraph)
library(paletteer)
library(igraph)
library(rdracor)
library(tidyverse)
library(rgexf)Сетевой анализ «Камер-фульерского журнала» В. Ф. Ходасевича
По данным за 1922 год
Сбор данных
Чтобы извлечь нужные намм данные из файлов GEXF, воспользуемся функцией.
all_files <- list.files(
path = 'dataverse_files-3',
pattern = "\\.gexf$",
full.names = TRUE
)
process_network <- function(file_path) {
# Читаем GEXF
gexf_obj <- read.gexf(file_path)
# Конвертируем в igraph для анализа
ig_obj <- gexf.to.igraph(gexf_obj)
# Пример анализа: считаем количество узлов, ребер и плотность
stats <- list(
name = basename(file_path),
nodes_count = vcount(ig_obj),
edges_count = ecount(ig_obj),
density = edge_density(ig_obj)
)
return(list(graph = ig_obj, stats = stats))
}
results <- lapply(all_files, process_network)
summary_table <- do.call(rbind, lapply(results, function(x) as.data.frame(x$stats)))
# Достаем только объекты igraph из списка результатов
all_graphs <- lapply(results, function(x) x$graph)
# Объединяем все графы в один (это и есть обобщение за год)
# union объединяет узлы с одинаковыми именами
year_graph <- do.call(igraph::union, all_graphs)
# Проверим, что получилось
vcount(year_graph)
ecount(year_graph)Итого уникальных персонажей за год — 112, уникальных связей — 707.
# Удалим изолированные узлы, то есть тех, кто ни с кем в этом году не взаимодействовал
year_graph <- delete.vertices(year_graph, V(year_graph)[degree(year_graph) == 0])Создание объединенной сети
set.seed(424242)
ggraph(year_graph, layout = "nicely") +
geom_edge_link(aes(alpha = ..index..), show.legend = FALSE, color = "grey") +
geom_node_point(aes(size = degree(year_graph)), color = "#2c3e50") +
geom_node_text(aes(label = name), repel = TRUE, size = 3, family = "sans") +
theme_graph() +
labs(
title = "Объединенная сеть персонажей за год",
subtitle = "На основе Камер-фурьерского журнала",
)В центре графа —плотный «комок» узлов с многочисленными связями. Это персоналии, которые чаще всего встречаются вместе и образуют устойчивую группу. По краям — разреженные углы; периферия — те, кто редко упоминается в журнале или связан лишь с парой других персонажей. Отдельные точки далеко от центра — фигуры, упомянутые в тексте, но практически не интегрированные в сеть взаимодействий.
Вычисляем лидеров
leaders <- data.frame(
name = V(year_graph)$name,
connections = degree(year_graph)
) |>
arrange(desc(connections)) |>
head(10)Явный центр — Белый с 60 связями, он заметно отрывается от остальных. Далее идёт плотная группа почти на одном уровне: Вишняк, Шкловский и Бахрах (по 41), затем Эренбург (40) и Горький (39). Ниже — Каплун (37), Гржебин и Лурье_В (по 34), Оцуп (33).
Точки сочленения и клики
# Точки сочленения
articulation_points(year_graph)
# Клики
clique_num(year_graph)
cliques(year_graph, min=13)Среди персонажей, удаление которых разрывает сеть на части —Зайцева_В, Женя, Слоним, Вишняк, Белый. Белый и Вишняк — фигуры ожидаемые. А вот Зайцева_В, Женя, Слоним —более интересные случаи. Их нет в топе по числу связей, но они все равно критичны.
Кликов четыре.
Первая группа ориентирована на издательскую и литературную деятельность, это «деловой» центр сети. Гржебин — ключевой издатель того времени, через которого проходили почти все. Присутствие Роде, владельца знаменитого ресторана «Вилла Роде», намекает, что эти связи могли фиксироваться на совместных встречах или банкетах.
Вторая группа пересекается с первой через фигуру Горького. Здесь присутствуют люди, постоянно входившие в его домашний быт.
Третий и четвертый клики почти идентичны — это группа интеллектуалов: философ Бердяев соседствует с критиков Бахрахом и поэтом Оцупом. В 1922 году они, вероятно, находились в ситуации непрерывного общения.
K-ядра
Было решено выбрать ядра 11, 12 и 13, поскольку с ядрами меньшей степени граф оказывался слишком «запутанным».
set.seed(424242)
year_11 <- induced_subgraph(year_graph, vids=V(year_graph)[core > 10])
ggraph(year_11, layout = "stress") +
geom_edge_link(color = cols[3],
alpha = 0.3,
width = 0.6) +
geom_node_point(aes(color = as.factor(core)),
size = 3,
show.legend = TRUE) +
geom_node_text(aes(filter = wDegree > 10,
label = name),
color = cols[3],
repel = TRUE) +
scale_color_brewer("k-ядра", type = "qual") +
theme_void()Получилась сверхплотная группа. Ядра вложены друг в друга: сначала идут Осоргины и имеющие с ними связь персонажи, затем — более узкий круг (Роде, Пинкевич, Нина, Желябужский, Миклашевский), далее — крайне важные фигуры, в том числе центральные авторы (Белый, Оцуп, Пастернак, Бердяев).
Нахождение сообществ
Было решено использовать несколько методов нахождения сообществ.
# Случайное блуждание
cw <- cluster_walktrap(year_graph)
membership(cw) |> head()
par(mar = rep(0, 4))
plot(cw, year_graph)
# Cluster spinglass
csg <- cluster_spinglass(year_graph)
membership(csg) |> head()
par(mar = rep(0, 4))
plot(csg, year_graph)
# Louvain
louvain <- cluster_louvain(year_graph)
membership(louvain) |> head()
par(mar = rep(0, 4))
plot(louvain, year_graph)Результаты применения алгоритма случайного блуждания таковы.
А вот что нам дало применение cluster spinglass. А это граф для алгоритма Лувена.
Чтобы понять, на результаты применения какого метода стоит обратить внимание, обратимся к значению модулярности для каждого из них.
Наиболее оправданным будет обращение к cluster spinglass. Модель нашла наиболее качественное разбиение: поскольку метод учитывает не только наличие ребер, но и их отсутствие, для сверхплотных сетей он может оказаться самом точным. Метод Лувена почти не отстает — значит, структура сообществ весьма устойчива. А вот «случайные блуждания» работают заметно хуже: алгоритм, «перепрыгивающий» между сообществами, сложнее понимает, где заканчивается одна группа и начинается другая.
Итак, в центре полученного путем применения cluster spinglass графа находятся «универсальные связные», принадлежащие сразу к нескольким контекстам (Белый, Эренбург, Бердяев, Одоевцева). Их сообщества накладываются друг на друга, образуя многослойное облако. Справа — Выгодский, Слоним, Григорович. Это более разреженная часть сети. Слева —Зернекау, Амфитеатров, Ларионов, Нончарова — также удаленная от центра группа. Возможно, эти люди принадлежали к кружкам, удаленным от «основного» узла, или находились географически далеко.