library(rgexf)
library(igraph)
library(tidyverse)
library(igraph)
Применение сетевого подхода к “Камер-фурьерскому журналу” В.Ф. Ходасевича
Данные представляют собой записи “Камер-фурьерского журнала” (КФЖ) Владислава Фелициановича Ходасевича. КФЖ — это рукописный текст, в котором Ходасевич фиксировал историю встреч с приятелями, знакомыми и друзьями в период эмиграции. Первая запись датирована 30 июня 1922 г. (приезд Ходасевича и Н. Н. Берберовой в Берлин). Обращение к архаичной форме камер-фурьерского журнала, с одной стороны, демонстрирует верность традициям Российской империи, а с другой – создаёт иллюзию оседлости. Ходасевич соблюдает канон «жанра» по основным параметрам: ежедневность записей, выдержанность стиля, разграничение публичного и приватного, внимание к парадной стороне жизни.
В качестве анализируемого периода выбран 1932 год — год расставания Ходасевича со своей первой женой Ниной Берберовой, которая стала появляться в записях Ходасевича только после разрыва супругов.
1 Импорт данных
В предоставленных данных каждый год “разбит” по месяцам. Импортируем данные за каждый месяц 1932 года в отдельности, а затем объединяем их и извлекаем необходимую информацию о встречах.
<- list.files("./months_data", pattern = "1932.*\\.gexf", full.names = TRUE)
gexf_files
<- lapply(gexf_files, read.gexf) gexf_data
<- data.frame()
all_edges
for (i in 1:length(gexf_data)) {
<- gexf_data[[i]]$edges
edges_table <- rbind(all_edges, edges_table)
all_edges
}
all_edges
<- all_edges |>
all_edges select(-id)
2 Создание объекта графа
На основе подготовленных данных создаем объект графа (igraph). Тип связи в данных ненаправленный, так как Ходасевич фиксирует свои наблюдения о его встречах с различными людьми. Тип связи задаю вручную.
<- graph_from_data_frame(
khodasevich_circle d = all_edges,
directed = FALSE
) khodasevich_circle
IGRAPH 85d9c6f UNW- 207 2778 --
+ attr: name (v/c), weight (e/n)
+ edges from 85d9c6f (vertex names):
[1] Именитов --Шильтян Именитов --жена_Шильтяна
[3] Именитов --Горчаков_МК Архангельский--Костанов
[5] Нина --Осоргина Нина --Макеев
[7] Нина --Фельзен Нина --Бахрах
[9] Нина --Смоленский Нина --Браславский
[11] Нина --Софроницкая Нина --Полонский
[13] Нина --Гончарова Марголин --Оля
[15] Зайцева_В --Абрамова Зайцева_В --Зайцев_Б
+ ... omitted several edges
Таким образом, граф является ненаправленным (undirected), именованным (named), то есть узлы имеют имена, а также взвешенным (weighted), то есть рёбра имеют вес. Граф не имеет других специальных атрибутов, например, временных меток. Количество узлов (вершин): 207. Количество рёбер: 2778.
3 Атрибуты рёбер
Теперь внимательнее посмотрим на атрибуты рёбер.
E(khodasevich_circle)
+ 2778/2778 edges from 85d9c6f (vertex names):
[1] Именитов --Шильтян Именитов --жена_Шильтяна
[3] Именитов --Горчаков_МК Архангельский--Костанов
[5] Нина --Осоргина Нина --Макеев
[7] Нина --Фельзен Нина --Бахрах
[9] Нина --Смоленский Нина --Браславский
[11] Нина --Софроницкая Нина --Полонский
[13] Нина --Гончарова Марголин --Оля
[15] Зайцева_В --Абрамова Зайцева_В --Зайцев_Б
[17] Полонский --Осоргина Полонский --Оля
[19] Полонский --Алданов Полонский --Марианна
+ ... omitted several edges
Проверяем количество ребер.
ecount(khodasevich_circle)
[1] 2778
Веса ребер хранят информацию о том, как часто упоминаемые личности встречаются с Ходасевичем, т. е. отражают силу связи.
edge_attr(khodasevich_circle, "weight")
Выведем ребра, вес которых больше 1.
E(khodasevich_circle)[weight > 1]
+ 451/2778 edges from 85d9c6f (vertex names):
[1] Ал_Минор --Тумаркин Тумаркин --Болотова_Шура
[3] Марианна --Оля Осоргина --Макеев
[5] Левинсонша --Мандельштам Алданов --Вольфсон
[7] Вольфсон --Зензинов Зайцева_В --Вольфсон
[9] Вольфсон --Керенский Вольфсон --Руднева
[11] Вольфсон --Цетлина Макеев --Вольфсон
[13] Вольфсон --Вольфсон_Э Вольфсон --Вишняк
[15] Вольфсон --Вишнячка Вольфсон --Зайцев_Б
[17] Вольфсон --Алданова Вольфсон --Цетлин
[19] Вольфсон --Бунина Мережковский--Гиппиус
+ ... omitted several edges
Другая характеристика сети – это ее плотность. Граф имеет относительно мало связей по сравнению с максимально возможным числом. Такие сети часто встречаются в настоящих данных, например, в социальных сетях, где каждый человек связан только с небольшой частью всех возможных контактов. Вспомним число Данбара, которое означает, что человек не может поддерживать больше 150 постоянных социальных связей.
edge_density(khodasevich_circle)
[1] 0.1302941
4 Атрибуты узлов
еще одна важная характеристика сети – это ее размер. Размер – это количество участников (members), которые называются вершинами (vertices), узлами или акторами. Рассмотрим вершины графа.
V(khodasevich_circle)
+ 207/207 vertices, named, from 85d9c6f:
[1] Именитов Архангельский Нина Марголин
[5] Зайцева_В Полонский Ник_Алеев Нюша
[9] Ал_Минор Вейдле Фельзен Шишмарева
[13] Бахрах Тумаркин Шильтян Браславский
[17] Каплун Абрамова Марианна Гончарова
[21] Осоргина Оля Терапиано Алданов
[25] Левинсон Макеев Левинсонша жена_Г_Лунца
[29] Вольфсон Мережковский Цетлина Кнут
[33] Голенищев-Кутузов Шполянская Керенский Руднева
[37] Городецкая Азов Вольфсон_Э Мандельштам
+ ... omitted several vertices
vcount(khodasevich_circle)
[1] 207
Определяем степень узлов.
<- as.numeric(degree(khodasevich_circle))
d V(khodasevich_circle)$degree <- d
khodasevich_circle
IGRAPH 85d9c6f UNW- 207 2778 --
+ attr: name (v/c), degree (v/n), weight (e/n)
+ edges from 85d9c6f (vertex names):
[1] Именитов --Шильтян Именитов --жена_Шильтяна
[3] Именитов --Горчаков_МК Архангельский--Костанов
[5] Нина --Осоргина Нина --Макеев
[7] Нина --Фельзен Нина --Бахрах
[9] Нина --Смоленский Нина --Браславский
[11] Нина --Софроницкая Нина --Полонский
[13] Нина --Гончарова Марголин --Оля
[15] Зайцева_В --Абрамова Зайцева_В --Зайцев_Б
+ ... omitted several edges
Теперь в графе отражается также степень вершин (узлов).
Важность (prominence) участника (актора, вершины, узла) определяется его положением внутри сети. Применительно к ненаправленным сетям говорят о центральности (центральный актор вовлечен в наибольшее количество связей, прямых или косвенных).
Выводим самые “влиятельные” вершины (те, у которых больше всего связей).
<- degree(khodasevich_circle)
degrees sort(degrees, decreasing = T)[1:10]
Алданов Нина Смоленский Мандельштам Вейдле Милочка
168 164 154 134 131 128
Вишняк Зайцев_Б Макеев Зайцева_В
125 120 119 117
Видно, что в 1932 году Нина занимает второе в сети место по центральности. Предположительно, это связано с тем, что Ходасевич искал встреч с бывшей женой (например, посещал те же места, что и она).
5 Визуализация графа
Визуализируем полный граф.
set.seed(210325)
plot(khodasevich_circle,
vertex.label = V(khodasevich_circle)$name,
vertex.size = 5,
vertex.label.cex = 0.8,
vertex.color = "black",
edge.color = "black",
vertex.label.color = "black",
edge.width = E(khodasevich_circle)$weight * 0.5,
layout = layout_with_kk(khodasevich_circle))
К сожалению, прочитать его в таком виде невозможно. Отираем связи по весу и отбрасываем наименее значимые, что позволит наглядно визуализировать граф.
<- E(khodasevich_circle)[weight > 2]
filtered_edges <- subgraph.edges(khodasevich_circle, filtered_edges) filtered_graph
set.seed(210325)
plot(filtered_graph,
vertex.size = 5,
vertex.label = V(filtered_graph)$name,
vertex.label.cex = 0.8,
edge.color = "#A5A684",
vertex.color = "#C37A89",
vertex.label.color = "black",
vertex.frame.color = "transparent",
edge.width = E(filtered_graph)$weight * 0.5,
layout = layout_with_fr(filtered_graph))
Граф распадается на два крупных кластера (в более мелкий входит Нина) и на один кластер, состоящий всего из двух персон - Клемм и Жуковский.
6 Подграф
Теперь выведем эго-граф для Нины Берберовой, чтобы отразить ее социальную сеть. Мы создаем (под)графы из всех соседей заданных вершин, т. е. таким образом мы находит дурзей и друзей друзей Нины Берберовой.
<- make_ego_graph(
p
khodasevich_circle,order = 2,
nodes = "Нина",
mode = "all"
1]]
)[[
p
IGRAPH 151d1dd UNW- 189 2755 --
+ attr: name (v/c), degree (v/n), weight (e/n)
+ edges from 151d1dd (vertex names):
[1] Нина --Осоргина Нина --Макеев Нина --Фельзен
[4] Нина --Бахрах Нина --Смоленский Нина --Браславский
[7] Нина --Софроницкая Нина --Полонский Нина --Гончарова
[10] Марголин --Оля Зайцева_В--Абрамова Зайцева_В--Зайцев_Б
[13] Полонский--Осоргина Полонский--Оля Полонский--Алданов
[16] Полонский--Марианна Полонский--Полонская Полонский--Макеев
[19] Нюша --Каплун Ал_Минор --Тумаркин Ал_Минор --Болотова_Шура
[22] Вейдле --Терапиано Вейдле --Мандельштам Фельзен --Браславский
+ ... omitted several edges
Для визуализации оставляем более значимые свзяи, т. е. отбираем рёбра с весом больше 3.
<- subgraph_from_edges(
p_filtered
p,eids = which(E(p)$weight > 3)
)
p_filtered
IGRAPH a6dba24 UNW- 22 53 --
+ attr: name (v/c), degree (v/n), weight (e/n)
+ edges from a6dba24 (vertex names):
[1] Марианна --Оля Вольфсон --Вольфсон_Э Зайцева_В--Зайцев_Б
[4] Зайцева_В--Алданов Алданов --Керенский Макеев --Керенский
[7] Керенский--Вишняк Керенский--Вишнячка Керенский--Алданова
[10] Алданов --Зайцев_Б Марианна --Оля Макеев --Алданова
[13] Алданов --Алданова Алданов --Макеев Алданов --Вишняк
[16] Алданов --Вишнячка Вишнячка --Вишняк Марианна --Оля
[19] Марианна --Оля Полонский--Полонская Зайцева_В--Зайцев_Б
[22] Марианна --Оля Нина --Терапиано Нина --Мандельштам
+ ... omitted several edges
7 Визуализация подграфа
Визуализируем отфильтрованные данные.
par(mar = rep(0,4), cex = 0.7)
<- layout_with_kk(p_filtered)
layout_p
set.seed(210325)
plot(p_filtered,
vertex.size = 6,
edge.arrow.size = 0.5,
vertex.label.dist = 0.5,
edge.curved = 0.2,
edge.color = "#A5A684",
vertex.color = "#C37A89",
vertex.label.cex = 1.2,
vertex.label.color = "black",
vertex.label = V(p_filtered)$name,
layout = layout_p,
vertex.frame.color = "transparent")
Теперь граф рассыпался на два условно крпуных кластера и три более мелких. Исходя из свидетельств, Берберова действительно была дружна с Мандельштамом. Примечательно, что во второй кластер входит Макеев - будущий супруг Берберовой (1936 г.). Отдельно отмечу, что если оставить связи со значением больше 5, в сети Нины останется всего один человек — Оля.
8 Анализ сообществ
Используем алгоритм “случайного блуждания” для определения сообществ.
<- cluster_walktrap(khodasevich_circle)
cw membership(cw) |> head()
Именитов Архангельский Нина Марголин Зайцева_В
18 19 7 6 4
Полонский
6
par(mar = rep(0, 4))
set.seed(2103)
plot(cw, khodasevich_circle)
Согласно результатам, сообщества скорее распадаются преимущественно на мелкие или средние группы, а также на совсем отдельные, состоящие всего из нескольких человек.
9 Модулярность
Проверить удачность используемого для определения сообществ алгоритма можно при помощи подсчета модулярности.
modularity(khodasevich_circle, membership(cw))
[1] 0.3627279
Пробуем сопаставить полученные результаты с другим алгоритмом обнаржуения сообществ.
<- cluster_infomap(khodasevich_circle)
test_infomap modularity(khodasevich_circle, membership(test_infomap))
[1] 0.07201374
Так как при выделении сообществ в большинстве случаев наша задача – максимизировать модулярность, алгоритм infomap оказывается менее продуктивным для наших данных. Хотя визуально он является более интерпретируемым.
par(mar = rep(0, 4))
set.seed(21.03)
plot(test_infomap, khodasevich_circle)
10 Точки сочленения и клики
Точка сочленения – это узел, при удалении которого увеличивается число компонент связности. Таким образом, они соединяют разные части сети. При их удалении акторы (узлы, вершины) не могут взаимодействовать друг с другом.
articulation_points(khodasevich_circle)
+ 9/207 vertices, named, from 85d9c6f:
[1] Именитов Каплун Крыжановская Муратов Вишняк
[6] Женя Оля Нина Костанов
Мы видим, что Нина является точкой сочленения, а значит её удаление приведет к тому, что некоторые акторы (узлы) больше не смогут взаимодействовать друг с другом. В целом точки сочленения, как правило, это люди, которые связывают разные группы (например, общие друзья в разных компаниях).
Клика – один из самых простых типов сплоченных подгрупп; это максимально полный подграф, т.е. подмножество узлов со всеми возможными связями между ними.
clique_num(khodasevich_circle)
[1] 25
cliques(khodasevich_circle, min=25)
[[1]]
+ 25/207 vertices, named, from 85d9c6f:
[1] Нина Зайцева_В Вейдле Тумаркин Осоргина
[6] Макеев Вольфсон Цетлина Шполянская Вольфсон_Э
[11] Зайцев_Б Цетлин Милочка Ася Аминадо
[16] Смоленский Болотова_Шура Трахтерев Маршак Гальперин
[21] Фондаминский Куприн Жаботинский Ремизов Руманов
largest_cliques(khodasevich_circle)
[[1]]
+ 25/207 vertices, named, from 85d9c6f:
[1] Маршак Нина Руманов Ремизов Жаботинский
[6] Куприн Фондаминский Гальперин Трахтерев Болотова_Шура
[11] Смоленский Аминадо Ася Милочка Цетлин
[16] Зайцев_Б Вольфсон_Э Шполянская Цетлина Вольфсон
[21] Макеев Осоргина Тумаркин Вейдле Зайцева_В
Клика из 25 узлов указывает на тесную группу, где все участники напрямую связаны друг с другом. Такие группы часто играют важную роль в распространении информации или влияния внутри сети.
Результаты проведенного сетевого анализа 1932 года подтверждают результаты исследования, опубликованного в статье “Цифровые подходы к «Камер-фурьерскому журналу» В. Ф. Ходасевича”. Нина Берберова стала появляться в записях Ходасевича только после разрыва. К этому времени она приобрела литературную известность; нет сомнения, что и раньше ее круг знакомств был широк, но до расставания Ходасевич фиксировал ее в журнале лишь изредка (когда она уезжала или возвращалась). На мой взгляд, такой характер записей говорит о слиянии Ходасевича и Берборовой в сознании Ходасевича, т.е. о восприятии жены как части себя. Ходасевич действительно фокусировал свое внимание на жизни Нины Берберовой, кроме у них очевидно был общий круг знакомых (что неудивительно), но удивительно как раз то, что он сохранился. Ходасевич не стал “затирать” ее из КФЖ, как он делал с другими людьми, c которыми у него было некоторое несовпадение (Адамович, например), а наоборот поместил ее в центр событий 1932 года.