library(igraph)
library(dplyr)
# Загружаем файлы
<- read.csv("edges07.csv", stringsAsFactors = FALSE)
edges <- read.csv("nodes05.csv", stringsAsFactors = FALSE)
nodes
# Посчитаем вес ребер (количество связей между двумя вершинами)
<- edges |>
edges_weighted group_by(edges_from, edges_to, year, type) |>
summarise(weight = n(), .groups = "drop")
# Создаём граф (на самом деле два - направленный и ненаправленный)
<- graph_from_data_frame(
g d = edges_weighted[, c("edges_from", "edges_to")],
vertices = nodes,
directed = FALSE
)
<- graph_from_data_frame(
g_dir d = edges_weighted[, c("edges_from", "edges_to")],
vertices = nodes,
directed = TRUE
)
# Передаём в граф атрибуты рёбер
E(g)$weight <- edges_weighted$weight
E(g)$year <- edges_weighted$year
E(g)$type <- edges_weighted$type
E(g_dir)$weight <- edges_weighted$weight
E(g_dir)$year <- edges_weighted$year
E(g_dir)$type <- edges_weighted$type
В сетях Парвуса:
сетевой анализ книжных изданий трудов И.Л.Гельфанда (Парвуса) из собрания ЦСПИ ГПИБ России
Библиотека Парвуса
Настоящее исследование приурочено к 100-летию со дня смерти русского и немецкого социалиста Израиля Лазаревича Гельфанда, более известного как Александр Львович Парвус (1867-1924).
Скандально известный публицист и предприниматель… Мало изучен, забыт. Актуальность работы по изучению интеллектуального наследия Парвуса была обозначена еще в 1970-е годы, когда Е.Гнедин писал «…в настоящее время некоторые политические шаги Парвуса это - сенсационная тема, которой на Западе посвящены новые работы, не только исторического характера. О научных и публицистических трудах Парвуса и его роли в рабочем движении появилась, насколько мне известно, только одна работа - кандидатская диссертация Винфреда Шарлау, изданная на правах рукописи в Мюнстере в 1964 году»[1].
Центр социально-политической истории (ЦСПИ)
ЦСПИ - филиал Государственной публичной исторической библиотеки России (ГПИБ России) - является преемником «центрального книгохранилища партии», объединившего в 1928-1931 гг. книжные фонды Института В.И. Ленина (ИЛ), Истпарта и Института К. Маркса и Ф. Энгельса (ИМЭ).
Было установлено, что в фондах ЦСПИ собрана, вероятно, одна из самых полных коллекций произведений Парвуса, включая многочисленные переиздания и переводы. Библиотека, комплектовавшаяся путем покупок, обмена и дарения, пополнялась как небольшими частными собраниями, так и приобретением крупных и ценных целостных коллекций [3].
Поиск материала осуществлялся по электронным каталогам трех крупнейших российских библиотек (РГБ, РНБ и ГПИБ), карточным каталогам ЦСПИ и электронной системе поиска книг Технологического института Карлсруэ. Исследование ограничено книжными изданиями трудов Парвуса без учета публикаций в периодической печати и листового материала, составляющего значительную часть коллекции библиотеки ЦСПИ.
Биобиблиография книжных изданий трудов
Терминами «биобиблиография» или «биобиблиографическая информация» будет обозначатся «вид библиографической информации, имеющий своим сущностным объектом интеллектуально-творческое наследие персоналий (персоналии), коллектива, воспроизводимое библиографическими средствами» [2].
В ходе исследовательской работы, проведенной весной 2024 года, создана небольшая биобиблиографическая база данных. По каждой единице хранения собраны не только выходные данные (место, дата публикации, количество страниц), но и максимально возможная дополнительная информация: язык оригинального текста и перевода, даты поступления в библиотеку, “доноры” собрания (библиотеки и коллекционеры, передавшие книги в ИЛ), инвентарные номера и библиотечные шифры, номера актов передачи книг в спецхран; описаны автографы, владельческие надписи, экслибрисы, штампы и маргиналии на книжных изданиях трудов Парвуса.
Полученные в результате исследования уникальные данные (принадлежность изданий к тому или иному собранию, наличие артефактов, помет и проч.), относящиеся как к научной и литературной биографии исследуемого, так и к истории книги и ее бытования, позволили выйти за рамки традиционного жанра персонального библиографического указателя. Во время написания статьи возникла идея изучения возможностей публикации разрабатываемого биобиблиографического ресурса как в традиционном, так и в электронном формате. Начат поиск новых способов и форм создания справочника, способных привлечь внимание бОльшего количества исследователей. Превращение собранных данных в математический объект и его визуализация - одно из таких решений.
Дизайн исследования: сети (графы)
Сетевой анализ данных заключается в построении модели системы объектов, имеющих связи друг с другом
Объектами (или вершинами) нашей сети были выбраны факты символического «владения» текстами произведений Парвуса (автор - издатель - читатель), а связями между ними (или ребрами сети) является процесс смены «владельца» (создание - издание - переиздание - перевод - покупка) произведения.
Загрузим необходимые данные и создадим граф.
Для создания графа на основе биобиблиографической базы данных были подготовлены два файла - один с вершинами (узлами), другой с ребрами.
Распечатаем информацию о наших графах.
Графы получились именованные, взвешенные. Граф “g” - ненаправленный, граф “g_dir” - направленный, в каждом по 493 вершины (узла) и 534 ребра. Говоря иначе, в нашей сети 493 объекта, связанных между собой 534 связями. Направленность графа означает, что известно направление связи объектов, от какого узла к какому она зафиксирована.
g
IGRAPH 42aed46 UNWB 493 534 --
+ attr: name (v/c), type (v/c), lang (v/c), year (v/c), book_details
| (v/c), nodes_ref (v/c), weight (e/n), year (e/n), type (e/c)
+ edges from 42aed46 (vertex names):
[1] 0 ; 97 | 35 --187039 0 ; 97 | 35 --541785
[3] 0 ; 97 | 35 --551581 0 ; 97 | 35 --618809
[5] 006 | 29 --1087293 006 | 29 ; 603 | 36 C1--332757
[7] 009 | 26 --Ц.5285 009 | 26 --Ц.5286
[9] 025 | 24 --1068573 025 | 24 --605054
[11] 080 | 25 --187038 080 | 25 --73171
[13] 096 | 24 --67378 1008 | 28 --1068569_2
+ ... omitted several edges
g_dir
IGRAPH 61e37cf DNWB 493 534 --
+ attr: name (v/c), type (v/c), lang (v/c), year (v/c), book_details
| (v/c), nodes_ref (v/c), weight (e/n), year (e/n), type (e/c)
+ edges from 61e37cf (vertex names):
[1] 0 ; 97 | 35 ->187039 0 ; 97 | 35 ->541785
[3] 0 ; 97 | 35 ->551581 0 ; 97 | 35 ->618809
[5] 006 | 29 ->1087293 006 | 29 ; 603 | 36 C1->332757
[7] 009 | 26 ->Ц.5285 009 | 26 ->Ц.5286
[9] 025 | 24 ->1068573 025 | 24 ->605054
[11] 080 | 25 ->187038 080 | 25 ->73171
[13] 096 | 24 ->67378 1008 | 28 ->1068569_2
+ ... omitted several edges
Распечатаем атрибуты вершин (vertex) и ребер (edges) нашего графа:
Атрибуты вершин: имя/name (v/c), тип/type (v/c), язык/lang (v/c), год/year (v/c), реф.узла/nodes_ref (v/c).
Значения атрибута вершины ‘type’: “книга”, “публикатор”, “владелец”, “инв.номер библиотеки”, “шифр полки”, “спецфонд”.
Атрибуты ребер: вес/weight (e/n), год/year (e/n), тип/type (e/c)
Значения атрибута ребра ‘type’: “издание”, “приобретение”, “поступление в библиотеку”, “размещение на полке”, “доступ запрещен”.
vertex_attr_names(g) # Список атрибутов вершин
[1] "name" "type" "lang" "year" "book_details"
[6] "nodes_ref"
unique(V(g)$type) # Список значений атрибута вершины 'type'
[1] "книга" "публикатор" "владелец экземпляра"
[4] "инв.номер библиотеки" "шифр полки" "спецфонд"
edge_attr_names(g) # Список атрибутов ребер
[1] "weight" "year" "type"
unique(E(g)$type) # Список значений атрибута ребер 'type'
[1] "поступление в библиотеку" "размещение на полке"
[3] "приобретение" "издание"
[5] "доступ запрещен"
Распечатаем некоторые значения вершин и направленных ребер нашего графа.
Здесь можно увидеть названия книг, издательств, номера и годы актов приема книг в библиотеку.
V(g_dir)[37:80] # Фрагмент списка вершин.
+ 44/493 vertices, named, from 61e37cf:
[1] Parvus_Marineforderungen Kolonialpolitik und Arbeiterinteressen
[2] Parvus_Sozialistische Zeitfragen
[3] Helphand_Technische Organisation der Arbeit
[4] Parvus_Wohin führt die politische Maßregelung
[5] Ленинград_Гос_изд-во
[6] Москва_Альпина_Паблишер
[7] СПб_Издание_Н.Глаголева
[8] Женева_Тип_Партии
[9] СПб_Прометей
[10] Баку_Типогр_Центр_комитета
+ ... omitted several vertices
E(g_dir)[320:370] # Фрагмент списка направленных ребер.
+ 51/534 edges from 61e37cf (vertex names):
[1] Kristiania_Norges soc.-dem. ungdomsforbund ->361 | 27
[2] Kristiania_Norges soc.-dem. ungdomsforbund ->365 | 27
[3] København_Nordiske Forfatteres Forlag ->700 | 28
[4] København_Socialdemokratiets Forlag "Fremad" ->700 | 28
[5] København_Udgivet af Socialdemokratisk Ungdomsforbund i Danmark->729 | 32
[6] LehmannParvus_Das hungernde Russland ->Stuttgart_Verlag von J.H.W.Dietz Nachf.
[7] Leipzig_Verlag der Leipziger Buchdruckerei Aktiengesellschaft ->080 | 25
+ ... omitted several edges
Анализ узлов и ребер
В этом разделе собраны расчеты, касающееся характеристик узлов и ребер нашей сети.
Веса вершин.
Вес - это количество связей вершины, то есть сколько ребер из нее выходит/входит. Посчитаем и запишем в атрибуты наших графов. Веса вершин ненаправленного и направленного графов не отличаются.
library(tidyverse)
<- edges |>
nodes_weighted pivot_longer(cols = c(edges_from, edges_to), names_to = "role", values_to = "node") |>
count(node, name = "weight")
V(g)$weight <- nodes_weighted$weight
V(g_dir)$weight <- nodes_weighted$weight
# Сравним веса вершин направленного и ненаправленного графов.
V(g)$weight[34:44]
[1] 8 4 2 2 4 1 1 1 2 4 2
V(g_dir)$weight[34:44]
[1] 8 4 2 2 4 1 1 1 2 4 2
ПОДСЧЕТ ЦЕНТРАЛЬНОСТИ ВЕРШИН.
(a) Degree centrality, центральность по степени - определяется количеством связей: чем больше прямых связей, тем более важным является узел. Рассчитывем, записываем в атрибуты, распечатываем фрагменты. Степени вершин ненаправленного и направленного графа в нашем случае совпадают.
V(g)$degree <- degree(g, mode = "all")
V(g_dir)$degree <- degree(g_dir, mode = "all")
# Центральность по степени вершин ненаправленного графа
V(g)$degree[44:54]
[1] 9 2 5 6 2 6 2 8 12 2 7
# Центральность по степени вершин направленного графа
V(g_dir)$degree[44:54]
[1] 9 2 5 6 2 6 2 8 12 2 7
# ТОП-10 вершин по Degree centrality
<- degree(g)
degrees sort(degrees, decreasing = T)[1:10]
Berlin_Verlag für Sozialwissenschaft
29
Berlin_Verlag Buchhandlung Vorwärts
28
Dresden_Kaden&Comp.
18
Parvus_Der Klassenkampf des Proletariats_Serie
17
700 | 28
17
Dresden_Verlag der "Sächsischen Arbeiter-Zeitung"
15
1100 | 28
15
200 | 27
13
800 | 27
13
СПб_Издание_Н.Глаголева
12
(b) Betweenness centrality - междуцентральность или центральность по посредничеству. Характеризует, насколько важную роль данный узел играет на пути “между” парами других узлов сети. Показывает, сколько раз вершина оказывается на кратчайших путях. Междуцентральность ненаправленного графа выше, чем направленного, поскольку пути можно проходить в обе стороны.
V(g)$betweenness <- betweenness(g, directed = FALSE, weights = E(g)$weight)
V(g_dir)$betweenness <- betweenness(g_dir, directed = TRUE, weights = E(g_dir)$weight)
# Междуцентральность вершин ненаправленного графа
V(g)$betweenness[44:54]
[1] 9088.00 429.00 2971.00 2979.00 2.00 36.00 424.00 6315.00
[9] 17331.02 28.00 108.00
# Междуцентральность вершин направленного графа
V(g_dir)$betweenness[44:54]
[1] 64 3 18 24 2 16 1 24 66 2 12
(c) Closeness centrality - центральность по близости говорит о том, насколько близко узел расположен к другим узлам сети. Центральность по близости – это величина, обратная сумме расстояний от узла i до всех остальных узлов сети. Одинакова для направленных и ненаправленных графов.
V(g)$closeness <- closeness(g, mode = "all", normalized = TRUE)
V(g_dir)$closeness <- closeness(g, mode = "all", normalized = TRUE)
V(g)$closeness[80:89]
[1] 0.1592593 0.1524823 0.1510362 0.7500000 0.1127130 0.1438608 0.1127130
[8] 0.1127130 0.1127130 0.1058852
V(g_dir)$closeness[80:89]
[1] 0.1592593 0.1524823 0.1510362 0.7500000 0.1127130 0.1438608 0.1127130
[8] 0.1127130 0.1127130 0.1058852
(d) Eigenvector centrality - центральность по собственному вектору, степень влиятельности. Показывает важность вершины в сети, учитывая влиятельность вершин, с которыми она взаимодействует. Не подходит для ацикличных и ориентированных (DAG) графов. Рассчитываем только для графа ‘g’. Записываем значения в атрибуты графа.
V(g)$eigen <- eigen_centrality(g, directed = FALSE, weights = E(g)$weight)$vector
V(g)$eigen[34:44]
[1] 3.508712e-05 2.126752e-04 8.187566e-04 9.447405e-04 7.017423e-06
[6] 5.817207e-18 9.447405e-04 4.985550e-06 3.718807e-05 6.217441e-06
[11] 1.456476e-03
# ТОП-5 вершин по Eigenvector centrality
<- eigen_centrality(g, directed = FALSE, weights = E(g)$weight)$vector
top5_eigen sort(top5_eigen, decreasing = T)[1:5]
Berlin_Verlag Buchhandlung Vorwärts
1.0000000
Parvus_Der Klassenkampf des Proletariats_Serie
0.9770779
781 | 25 ; 800 | 27 ; 200 | 27 ; 1175 | 27
0.1816111
800 | 27
0.1047828
Варна_Издание на Георги Бакаловъ_Печатница "Взаимность"
0.0764949
(e) PageRank - это алгоритм, изначально разработанный для оценки важности веб-страниц (Google). Он оценивает “вес” вершины в графе на основе количества и качества входящих рёбер и подходит для DAG графов. Рассчитаем PageRank для нашего направленного графа ‘g_dir’, оказавшегося ацикличным (DAG).
is_dag(g_dir)
[1] TRUE
V(g_dir)$pagerank <- page_rank(g_dir, directed = TRUE, weights = E(g_dir)$weight)$vector
V(g_dir)$pagerank[78:88]
[1] 0.001498919 0.001565105 0.001285653 0.001186374 0.001186374 0.002160779
[7] 0.001535321 0.001755596 0.001535321 0.001535321 0.001535321
# ТОП-5 вершин по PageRank
<- page_rank(g_dir, directed = TRUE, weights = E(g_dir)$weight)$vector
top5_pagerank sort(top5_pagerank, decreasing = T)[1:5]
ЕН240/З115 ЕН322/И911 Р
0.011678288 0.011203228
ЦА20/Т893 Berlin_Verlag für Sozialwissenschaft
0.010897707 0.006789073
700 | 28
0.006311528
(f) WeightedDegree - взвешенная центральность по степени. Тесно связана с понятием веса ребра. В отличие от простой центральности, она учитывает вес связанных с узлом ребер. Рассчитаем и запишем в атрибуты узлов. Направленность узла не влияет на значение этого атрибута.
V(g)$weightedDegree <- strength(g)
V(g_dir)$weightedDegree <- strength(g_dir)
#weightedDegree ненаправленного графа
V(g)$weightedDegree[78:88]
[1] 4 4 4 2 2 2 2 4 2 2 2
#weightedDegree направленного графа
V(g_dir)$weightedDegree[78:88]
[1] 4 4 4 2 2 2 2 4 2 2 2
# ТОП-10 вершин по Degree centrality
<- strength(g)
wDegree sort(wDegree, decreasing = T)[1:10]
Berlin_Verlag Buchhandlung Vorwärts
74
Berlin_Verlag für Sozialwissenschaft
60
Parvus_Der Klassenkampf des Proletariats_Serie
54
Dresden_Kaden&Comp.
34
Dresden_Verlag der "Sächsischen Arbeiter-Zeitung"
32
СПб_Издание_Н.Глаголева
22
СПб_Книгоиздательство "Новый Мир"
22
1100 | 28
22
700 | 28
22
Женева_Тип_Партии
20
Сохраним и распечатаем таблицы с рассчитанными значениями атрибутов вершин наших графов.
library(tibble)
<- get.data.frame(g, what = "vertices")
g_v_attr
<- get.data.frame(g_dir, what = "vertices")
g_dir_v_attr
# Атрибуты вершин ненаправленного графа
head(g_v_attr, 50)
# Атрибуты вершин направленного графа
head(g_dir_v_attr, 50)
Подграфы
Визуализация полного графа недостаточно информативна. Для решения исследовательских задач создадим и визуализируем подграфы, содержащие отфильтрованные подмножества вершин и рёбер исходного графа.
(а) Фильтрация на основе атрибутов вершин.
Для индуцированного подграфа (induced subgraph) мы отфильтровали узлы, с атрибутом ‘lang’ = “немецкий”, являющиеся соседями узла “Berlin_Verlag für Sozialwissenschaft”. Не все узлы (книги Парвуса) с выбранным языковым атрибутом соединены ребрами с узлом издательства, поскольку были опубликованы в других местах.
<- which(vertex_attr(g_dir)$lang == "немецкий")
deutch
<- induced_subgraph(g_dir, vids = deutch)
de
de
IGRAPH 5304aed DNWB 34 12 --
+ attr: name (v/c), type (v/c), lang (v/c), year (v/c), book_details
| (v/c), nodes_ref (v/c), weight (v/n), degree (v/n), betweenness
| (v/n), closeness (v/n), pagerank (v/n), weightedDegree (v/n), weight
| (e/n), year (e/n), type (e/c)
+ edges from 5304aed (vertex names):
[1] Parvus_Im Kampf um die Wahrheit ->Berlin_Verlag für Sozialwissenschaft
[2] Parvus_Die Soziale Bilanz des Krieges->Berlin_Verlag für Sozialwissenschaft
[3] Parvus_Aufbau und Wiedergutmachung ->Berlin_Verlag für Sozialwissenschaft
[4] Parvus_Meine Antwort an Kerenski ->Berlin_Verlag für Sozialwissenschaft
+ ... omitted several edges
neighbors(g_dir, "Berlin_Verlag für Sozialwissenschaft")
+ 21/493 vertices, named, from 61e37cf:
[1] 700 | 28 1538 | 28 644 | 24 ; ?
[4] 729 | 32 2550 824 | 36C2
[7] 825 | 36C2 800 | 27 390 | 34
[10] 895 | 25 TODO_41 II. 942 | 35? ; 729 | 32
[13] 896 | 27 2328 1448 | 26
[16] 722 | 32 255 | 31 633 | 32
[19] 9287 | 28 305 |35 2330
<- induced_subgraph(g_dir, vids = c(deutch, neighbors(g, "Berlin_Verlag für Sozialwissenschaft")))
de2
plot(de2)
(b) Создадим ego-граф - подграф, построенный вокруг одной выбранной вершины (это по-прежнему издательство “Berlin_Verlag für Sozialwissenschaft”) и содержащий всех её соседей на определённом расстоянии (в нашем случае order = 2). Визуализируем его в милых сердцу цветах. Оценим размер получившегося подграфа.
Для интерпретации полученной сети необходимы дополнительные размышления и исследования.
<- make_ego_graph(
de3
g_dir,order = 2,
nodes = "Berlin_Verlag für Sozialwissenschaft",
mode = "all"
1]]
)[[
# функция позволит распечатать все ребра
#print_all(de3)
de3
IGRAPH 63885b5 DNWB 98 107 --
+ attr: name (v/c), type (v/c), lang (v/c), year (v/c), book_details
| (v/c), nodes_ref (v/c), weight (v/n), degree (v/n), betweenness
| (v/n), closeness (v/n), pagerank (v/n), weightedDegree (v/n), weight
| (e/n), year (e/n), type (e/c)
+ edges from 63885b5 (vertex names):
[1] Parvus_Im Kampf um die Wahrheit ->Москва_Альпина_Паблишер
[2] Parvus_Im Kampf um die Wahrheit ->Berlin_Verlag für Sozialwissenschaft
[3] Parvus_Im Kampf um die Wahrheit ->København_Nordiske Forfatteres Forlag
[4] Parvus_Die Soziale Bilanz des Krieges->Стокгольм_Издание журнала "Извне"
+ ... omitted several edges
par(mar = rep(0,4), cex = 0.7)
<- layout_with_kk(de3)
layout_de3
plot(de3, vertex.size=6,
edge.arrow.size = 0.4,
vertex.label.dist = 1,
edge.curved = 0.2,
edge.color = "black",
vertex.color = "darkred",
layout = layout_de3)
# размер подграфа
ego_size(g_dir,
order = 2,
nodes = "Berlin_Verlag für Sozialwissenschaft",
mode = "all")
[1] 98
(c) Визуализируем ego-граф для книги “Parvus_Im Kampf um die Wahrheit” (В борьбе за правду). Выберем способ укладки сети: dh (Davidson-Harel).
<- make_ego_graph(
ego_wahr
g_dir,order = 2,
nodes = "Parvus_Im Kampf um die Wahrheit",
mode = "all"
1]]
)[[
ego_wahr
IGRAPH 7b919f7 DNWB 35 36 --
+ attr: name (v/c), type (v/c), lang (v/c), year (v/c), book_details
| (v/c), nodes_ref (v/c), weight (v/n), degree (v/n), betweenness
| (v/n), closeness (v/n), pagerank (v/n), weightedDegree (v/n), weight
| (e/n), year (e/n), type (e/c)
+ edges from 7b919f7 (vertex names):
[1] Parvus_Im Kampf um die Wahrheit ->Москва_Альпина_Паблишер
[2] Parvus_Im Kampf um die Wahrheit ->Berlin_Verlag für Sozialwissenschaft
[3] Parvus_Im Kampf um die Wahrheit ->København_Nordiske Forfatteres Forlag
[4] Parvus_Der Klassenkampf des Proletariats_Serie->København_Nordiske Forfatteres Forlag
+ ... omitted several edges
library(gridExtra)
library(ggraph)
library(paletteer)
# трехцветная палитра
<- c("#FFE7B8", "#9B251E", "#7570B3")
cols
<- c("dh", "graphopt", "fr", "kk")
layouts
<- function(layout) {
plot_graph <- ggraph(ego_wahr, layout = layout) +
g1 geom_edge_link() +
geom_node_point(aes(size = degree,
fill = type),
show.legend = FALSE,
shape = 21,
color = "black"
+
) #geom_node_text(aes(label = name)) +
scale_fill_manual(values = cols) +
scale_size(guide = 'none') +
theme_graph(base_family = "sans") +
labs(title = layout)
return(g1)
}
set.seed(20032025)
ggraph(ego_wahr, layout = "dh", maxiter = 100) +
# тип линии вместо цвета, убираем стрелку
geom_edge_arc(aes(linetype = type),
color = "grey50",
strength = 0.2
+
) geom_node_point(aes(size = degree,
fill = type),
shape = 21,
color = "black"
+
) geom_node_text(aes(label = name), nudge_y = 0.7) +
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")
Характеристика графов в целом
РАССЧИТАЕМ ПЛОТНОСТЬ НАШИХ ГРАФОВ.
Graph density (плотность графа) - мера, показывающая, насколько граф заполнен рёбрами по сравнению с максимально возможным числом рёбер. Направленность графа влияет на его плотность.
# Плотность ненаправленного графа
<- edge_density(g)
g_graph_density print(g_graph_density)
[1] 0.004403107
# Плотность направленного графа
<- edge_density(g_dir)
g_dir_graph_density print(g_dir_graph_density)
[1] 0.002201553
КОМПОНЕНТЫ
Компонента сети – это подгруппа, где все акторы связаны между собой прямо или косвенно. Предварительно предположу, что в основе деления на компоненты внутри нашей сети лежат временные и географические характеристики “владения” текстами.
# Количество компонент сети
components(g)$no
[1] 9
# Размер компонент
components(g)$csize
[1] 431 4 18 17 4 4 7 4 4
# Узлы графа, относящиеся к 9 компоненте
which(components(g)$membership == 9)
Helphand_Technische Organisation der Arbeit
39
Uster-Zürich_Druck von A.Diggelmann
83
845 | 25
225
452392
454
ДИАМЕТР
Диаметр сети – количество шагов, которые нужно пройти, чтобы попасть из узла А в узел B; для сетей с несколькими компонентами учитывается та, что больше. Сначала вычисляются кратчайшие пути (геодезическое расстояние) между каждой парой узлов, затем из них берется максимальный.
<- largest_component(g)
lc_g diameter(lc_g, directed =TRUE)
[1] 28
get_diameter(lc_g)
+ 12/431 vertices, named, from bd550c7:
[1] Парвус_Открытое письмо Тверскому комитету
[2] Женева_Б.и.
[3] 1100 | 28
[4] Berlin_Verlag Buchhandlung Vorwärts
[5] 200 | 27
[6] СПб_Книгоиздательство "Новый Мир"
[7] 1279 | 26
[8] СПб_Издание_Н.Глаголева
[9] Парвус_Россия и революция
[10] Москва_URSS, ЛЕНАНД
+ ... omitted several vertices
farthest_vertices(lc_g)
$vertices
+ 2/431 vertices, named, from bd550c7:
[1] Парвус_Открытое письмо Тверскому комитету
[2] 527482
$distance
[1] 28
# Рассчитаем самую короткий путь между двумя книжными коллекциями, "донорами" ИЛ.
shortest_paths(lc_g, from = "1100 | 28", to = "700 | 28")
$vpath
$vpath[[1]]
+ 5/431 vertices, named, from bd550c7:
[1] 1100 | 28 Berlin_Verlag Buchhandlung Vorwärts
[3] 390 | 34 Berlin_Verlag für Sozialwissenschaft
[5] 700 | 28
$epath
NULL
$predecessors
NULL
$inbound_edges
NULL
ТРАНЗИТИВНОСТЬ
Коэффициент кластеризации, или транзитивность, отражает тенденцию к созданию закрытых треугольников, т.е. к замыканию. Транзитивность определяется как доля закрытых треугольников по отношению к общему количеству открытых и закрытых треугольников.
transitivity(g)
[1] 0
transitivity(g_dir)
[1] 0
ЦЕНТРАЛИЗАЦИЯ
Функция centr_clo() по умолчанию работает с ненаправленными графами. Рассчитаем ее значение для графа ‘g’.
centr_clo(g)$centralization
[1] 1.088314
ТОЧКИ СОЧЛЕНЕНИЯ
Точка сочленения – это узел, при удалении которого увеличивается число компонент связности. Таким образом, они соединяют разные части сети. При их удалении акторы (узлы, вершины) не могут взаимодействовать друг с другом.
articulation_points(g)
+ 181/493 vertices, named, from 42aed46:
[1] Dresden_Verlag der "Sächsischen Arbeiter-Zeitung"
[2] Leipzig_Verlag der Leipziger Buchdruckerei Aktiengesellschaft
[3] 2302
[4] Москва_Альпина_Паблишер
[5] Parvus_Im Kampf um die Wahrheit
[6] 2315
[7] София_Издава Партийната Социалистическа Книжарница
[8] 1224 | 7
[9] Parvus_Der Klassenkampf des Proletariats_Serie
[10] 600 | 1930
+ ... omitted several vertices
Точки сочленения тесто связаны с центральностью по посредничеству.
V(g)[betweenness > 1000.0]
+ 71/493 vertices, named, from 42aed46:
[1] Parvus_Im Kampf um die Wahrheit
[2] Parvus_Der Klassenkampf des Proletariats_Serie
[3] Parvus_Die Soziale Bilanz des Krieges
[4] Parvus_In der russischen Bastille während der Revolution
[5] Parvus_Der Opportunismus in der Praxis
[6] Парвус_Россия и революция
[7] Parvus_Die Handelskrisis und die Gewerkschaften
[8] Ленинград_Гос_изд-во
[9] СПб_Издание_Н.Глаголева
[10] Женева_Тип_Партии
+ ... omitted several vertices
V(g_dir)[betweenness > 10.0]
+ 65/493 vertices, named, from 61e37cf:
[1] Ленинград_Гос_изд-во
[2] СПб_Издание_Н.Глаголева
[3] Женева_Тип_Партии
[4] Баку_Типогр_Центр_комитета
[5] Женева_Б.и.
[6] СПб_Издание_С.Н.Салтыкова
[7] Варна_Издание на Георги Бакаловъ_Печатница "Взаимность"
[8] СПб_Книгоиздательство "Новый Мир"
[9] СПб_Издание О.Н. Поповой
[10] Константинополь_Друкарня Союзу Визволения Украïни
+ ... omitted several vertices
Анализ сообществ
АЛГОРИТМЫ ОБНАРУЖЕНИЯ ПОДГРУПП И СООБЩЕСТВ
Клики
Один из способов взглянуть на подгруппы сети заключается в исследовании социальной сплочености (cohesion). Сплоченные подгруппы - это множество акторов, которые объединены между собой посредством многочисленных, сильных и прямых связей. Клика – один из самых простых типов сплоченных подгрупп; это максимально полный подграф, т.е. подмножество узлов со всеми возможными связями между ними. Рассчитаем размер наибольшей клики в нашем графе. Он составляет всего 2 узла.
clique_num(g)
[1] 2
K-ядра
Популярным определением социальной сплоченности является k-ядро (k-core). Это максимальный подграф, в котором каждая вершина связана минимум с k другими вершинами этого же подграфа.
# K-ядерная структура
<- coreness(g)
cores_g head(cores_g)
Парвус_Без_царя_а_правительство_рабочее Parvus_Im Kampf um die Wahrheit
1 2
Парвус_В_рядах_германской_соцдемократии Парвус_В_чем_мы_расходимся?
1 1
Парвус_Борьба_культур_в_Германии Парвус_Война_и_революция
1 2
# Количество вершин в ядрах
table(cores_g)
cores_g
1 2 4
386 105 2
# Создаем новый атрибут вершин
V(g)$core <- cores_g
# Распечатываем список атрибутов ненаправленного графа
names(vertex_attr(g))
[1] "name" "type" "lang" "year"
[5] "book_details" "nodes_ref" "weight" "degree"
[9] "betweenness" "closeness" "eigen" "weightedDegree"
[13] "core"
Удалим k-ядра степени 1 и распечатаем результат
<- induced_subgraph(g, vids=V(g)[core > 1])
g2_4
ggraph(g2_4, layout = "kk", maxiter = 500) +
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 = degree > 10,
label = name),
color = cols[3],
repel = TRUE) +
scale_color_brewer("k-ядра", type = "qual") +
theme_void()
МОДУЛЯРНОСТЬ
Модулярность — одна из мер структуры сетей или графов. Мера была разработана для измерения силы разбиения сети на модули (называемые группами, кластерами или сообществами). Сети с высокой модулярностью имеют плотные связи между узлами внутри модулей, но слабые связи между узлами в различных модулях.
Модулярность равна доле рёбер от общего числа рёбер, которые попадают в данные группы, минус ожидаемая доля рёбер, которые попали бы в те же группы, если бы они были распределены случайно. Если все узлы принадлежат к одному классу, то модулярность равна нулю. Если разбиение на классы хорошее, то модулярность должна быть высокая.
Применим несколько алгоритмов рассчета модулярности.
Алгоритм Walktrap, алгоритм “случайного блуждания”. Распечатаем фрагмент обнаруженных модулей и их состава.
<- cluster_walktrap(g)
cw membership(cw) |> head()
Парвус_Без_царя_а_правительство_рабочее Parvus_Im Kampf um die Wahrheit
10 5
Парвус_В_рядах_германской_соцдемократии Парвус_В_чем_мы_расходимся?
2 6
Парвус_Борьба_культур_в_Германии Парвус_Война_и_революция
12 3
modularity(cw)
[1] 0.6802114
print(cw)[6:8]
IGRAPH clustering walktrap, groups: 92, mod: 0.68
+ groups:
$`1`
[1] "Parvus_Die Gewerkschaften und die Sozialdemokratie"
[2] "Parvus_Marineforderungen Kolonialpolitik und Arbeiterinteressen"
[3] "Parvus_Wohin führt die politische Maßregelung"
[4] "Dresden_Verlag der \"Sächsischen Arbeiter-Zeitung\""
[5] "0 ; 97 | 35"
[6] "080 | 25"
[7] "2530"
[8] "2500"
[9] "1166 | 25"
+ ... omitted several groups/vertices
$`6`
[1] "Парвус_В_чем_мы_расходимся?" "Парвус_До 9 января Предисловие"
[3] "Женева_Тип_Партии" "009 | 26"
[5] "025 | 24" "1109 | 28"
[7] "2305" "2306"
[9] "1008 | 28" "Ц.5285"
[11] "Ц.5286" "605054"
[13] "1068569" "1068573"
[15] "1068571" "1068572"
[17] "1068569_2" "ЦА20/Т893"
[19] "СФ-44998" "СФ-49667"
[21] "СФ-44999" "СФ-45000"
[23] "СФ-44997"
$`7`
[1] "Parvus_In der russischen Bastille während der Revolution"
[2] "СПб_Изд. \"Шиповник\""
[3] "195 | 24"
[4] "1030 | 25"
[5] "60670"
[6] "60671"
[7] "67379"
$`8`
[1] "LehmannParvus_Das hungernde Russland"
[2] "Stuttgart_Verlag von J.H.W.Dietz Nachf."
[3] "200 | 24"
[4] "647 | 333 ; 0"
[5] "286700"
[6] "158673"
[7] "111324"
Алгоритм “главный собственный вектор”
<- cluster_leading_eigen(g)
cev modularity(cev)
[1] 0.7460878
print(cev)[6:8]
IGRAPH clustering leading eigenvector, groups: 66, mod: 0.75
+ groups:
$`1`
[1] "Парвус_Без_царя_а_правительство_рабочее"
[2] "Ленинград_Гос_изд-во"
[3] "2506"
[4] "1165 | 25"
[5] "1061 | 25"
[6] "2300"
[7] "2301"
[8] "728491"
[9] "212902"
+ ... omitted several groups/vertices
$`6`
[1] "Parvus_Chwila obecna w Królestwie" "Warszawa_NA"
[3] "1200 | 28?" "96209"
$`7`
[1] "LehmannParvus_Das hungernde Russland"
[2] "Stuttgart_Verlag von J.H.W.Dietz Nachf."
[3] "200 | 24"
[4] "647 | 333 ; 0"
[5] "286700"
[6] "158673"
[7] "111324"
$`8`
[1] "Parvus_Der Anfang vom Ende?: Aus der Weltpolitik"
[2] "München_Druck und Verlag Richard Etzold"
[3] "177 | 32"
[4] "222008600"
Алгоритм Louvain. Это алгоритм дал самый высокий результат модулярности. Визуализируем его без имен вершин.
<- cluster_louvain(g)
cll
modularity(cll)
[1] 0.8387788
print(cll)[5:7]
IGRAPH clustering multi level, groups: 23, mod: 0.84
+ groups:
$`1`
[1] "Парвус_Без_царя_а_правительство_рабочее"
[2] "Ленинград_Гос_изд-во"
[3] "2506"
[4] "1165 | 25"
[5] "1061 | 25"
[6] "2300"
[7] "2301"
[8] "728491"
[9] "212902"
+ ... omitted several groups/vertices
$`5`
[1] "Парвус_Война_и_революция"
[2] "Парвус_Открытое письмо Тверскому комитету"
[3] "Баку_Типогр_Центр_комитета"
[4] "Женева_Б.и."
[5] "1100 | 28"
[6] "207 | 31"
[7] "600 | 30"
[8] "696 | 32"
[9] "270 | 28"
[10] "390 | 25"
[11] "1560"
[12] "Ц.5283"
[13] "Ц.5284"
[14] "Ц-896"
[15] "Ц-897"
[16] "Ц-898"
[17] "Ц-895"
[18] "Ц-5287"
[19] "Ц-5288"
[20] "Ц-5289"
[21] "Ц-5290"
[22] "Ц-5291"
[23] "Ц.5292"
[24] "Ц.5293"
[25] "Ц.5294"
[26] "Ц.5295"
[27] "Ц.5296"
[28] "289190"
$`6`
[1] "Парвус/Parvus_Стачка??" "СПб: Американская Скоропечатня"
[3] "2304" "609273"
$`7`
[1] "Parvus_Tua res agitur" "СПб_Издание_С.Н.Салтыкова"
[3] "349 | 25" "504 | 26"
[5] "481 | 30" "2307"
[7] "2308" "203019 (18)"
[9] "547732" "1075140"
[11] "1075141" "1075142"
[13] "ЕН240/З115" "СФ-29734"
[15] "СФ-29733" "СФ-29551"
[17] "СФ-29552" "СФ-42336"
par(mar = rep(0, 4))
plot(cll, g, vertex.label = NA)
SUMMARY
Для ненаправленного графа
<- vcount(g)
size <- edge_density(g)
density <- degree(g)
degree_values <- max(degree_values)
max_degree <- V(g)$name[which.max(degree_values)]
max_degree_v <- diameter(g)
diameter_value <- mean_distance(g)
avg_distance <- centr_clo(g)$centralization
closeness_centralization <- transitivity(g, type = "global")
global_clustering <- cohesion(g)
cohesion_value <- assortativity_degree(g)
assortativity_value
print(paste("Размер (количество вершин):", size))
[1] "Размер (количество вершин): 493"
print(paste("Плотность:", round(density, 3)))
[1] "Плотность: 0.004"
print(paste("Максимальная степень:", max_degree, "(", max_degree_v, ")"))
[1] "Максимальная степень: 29 ( Berlin_Verlag für Sozialwissenschaft )"
print(paste("Диаметр графа:", diameter_value))
[1] "Диаметр графа: 28"
print(paste("Среднее расстояние:", round(avg_distance, 2)))
[1] "Среднее расстояние: 8.66"
print(paste("Централизация графа:", round(closeness_centralization, 2)))
[1] "Централизация графа: 1.09"
print(paste("Глобальная кластеризация:", global_clustering))
[1] "Глобальная кластеризация: 0"
print(paste("Коэзия:", cohesion_value))
[1] "Коэзия: 0"
print(paste("Ассортативность:", round(assortativity_value, 2)))
[1] "Ассортативность: -0.09"
Визуализация графов
Как сказал в личной беседе Борис Валерьевич Орехов:
“В сети дело не в визуализации. Она — дополнительный инструмент, соус, вишенка, но не сам торт. Главное в сетевом анализе — это представление данных в виде математического объекта.” — Б.В. Орехов, кандидат филологических наук, доцент Школы лингвистики и руководитель образовательной программы «Цифровые методы в гуманитарных науках» НИУ ВШЭ, старший научный сотрудник ИРЛИ РАН (Пушкинский Дом).
ПАРА ВИШЕНОК С ТОРТА ПАРВУСА
Визуализации данных, представленных в данном разделе сделаны с помощью сервиса RAWGraphs 2.0 в рамках мастер-классов Надежды Андриановой.
Treemap
Древовидная диаграмма, treemap - способ визуализации данных иерархической структуры в виде прямоугольников, площадь которых пропорциональна значению отображаемой записи.
На представленной диаграмме цветом обозначена доля от целого для каждого из 25 городов, в чьих типографиях печатались труды Парвуса из нашей коллекции. Обнаруженные 231 единица хранения была отпечатана в 61 типографии 25 европейских городов.
Bipartite graph
Двудольный граф или биграф - граф, множество вершин которого можно разбить на две части таким образом, что каждое ребро графа соединяет какую-то вершину из одной части с какой-то вершиной другой части.
Наш биграф помог разобраться с языками оригиналов трудов Парвуса. Говоря проще, стало понятнее на каком языке чаще всего писал свои работы Парвус. Надо бы еще визуализировать закономерности использования фрактуры, но это в следующий раз.
Прочие визуализаци
По этой ссылке можно познакомиться с интерактивной визуализацией графа для одной из работ Парвуса - “Die Soziale Bilanz des Krieges”, написанной в 1917 году, переведенный минимум на 5 языков и представленной в собрании ЦСПИ 9 единицами хранения.
Итоги и рефлексия
Все посчиталось и ЧТО?
Рассчеты проделаны, данные визуализированы, теперь самое время задуматься над тем, как интерпретировать полученные результаты.
Что нового мы узнали и есть ли здесь что-то такое, что не могло быть получено без использования сетевого анализа? Пока на эти вопросы нет ответов…
Транснациональный социалист ПАРВУС
НО! один результат все же есть. Благодаря размышлениям над первыми результатами в поле нашего зрения попал ранее незнакомый термин, который очень подходит нашему герою: “транснациональный социалист” - человек, политическая и интеллектуальная деятельность которого выходит далеко за рамки одной страны. Безусловно, это о Парвусе.