library(igraph)
library(ggplot2)
library(ggraph)
library(tidyverse)
library(udpipe)Работа с графами
Компьютерный анализ текстов, занятие 19
Импорт необходимых библиотек среды R
Подготовка данных
В данном задании попробуем визуализировать, какие употребительные коллокации можно зафиксировать в рамках сочетаний существительных и глаголов в латинском датасете, предложенном для анализа:
# практикуемся в создании графов на латинском датасете
caesar <- udpipe_read_conllu('https://github.com/locusclassicus/text_analysis_2024/raw/main/files/bg_latinpipe.conllu')
# смотрим на состав лемм, в relevant отбираем только NOUN и VERB
co_occur <- cooccurrence(caesar$lemma,
relevant = caesar$upos %in% c('NOUN', 'VERB'),
skipgram = 1) |>
as_tibble() |>
filter(cooc > 8)В полученном tibble’е фиксируется 29 наблюдений, если filter(cooc > 8), что вполне поддаётся визуализации. Если задать filter(cooc > 5), получится 85 наблюдений, но при этом для визуализации это поддаётся существенно хуже.
Создание графа
Здесь я предлагаю доработать получившийся граф:
co_occur_g <- graph_from_data_frame(co_occur)
co_occur_gIGRAPH 89dee5c DN-- 40 29 --
+ attr: name (v/c), cooc (e/n)
+ edges from 89dee5c (vertex names):
[1] res ->cognosco tribunus ->miles bellum ->gero
[4] iter ->facio proelium ->committo fero ->possum
[7] bellum ->infero obses ->do legatus ->mitto
[10] res ->gero sustineo ->possum impetus ->facio
[13] castra ->educo locus ->castra consilium ->capio
[16] hostis ->impetus praesidium->relinquo pars ->flumen
[19] locus ->natura flumen ->transeo hostis ->castra
[22] signum ->do impero ->facio castra ->venio
+ ... omitted several edges
Граф направленный (D), 40 вершин и 29 связей, что логично, так как в исходном co_occur 29 наблюдений.
В граф можно добавить информацию о том, какою частью речи является та или иная вершина. Список лемм и их частеречной принадлежности можно выделить из основной таблицы caesar. Оставляю только NOUN и VERB.
caesar_pos <- caesar |>
filter(lemma %in% V(co_occur_g)$name) |>
select(lemma, upos) |>
unique() |>
filter(upos %in% c('VERB', 'NOUN'))При этом длины векторов caesar_pos$lemma и V(co_occur_g)$name отличаются:
length(caesar_pos$lemma)[1] 41
length(V(co_occur_g)$name)[1] 40
Дело в двойном прочтении mitto как глагола или существительного. Оно фигурирует в составе сочетания legatus + mitto. Из анализа я решился исключить менее вероятное прочтение: mitto будет представлено исключительно как VERB.
pos_tbl <- caesar_pos |>
filter(!(lemma == 'mitto' & upos == 'NOUN'))Сохраняем информацию о частях речи:
V(co_occur_g)$pos <- pos_tbl$upos
co_occur_gIGRAPH 89dee5c DN-- 40 29 --
+ attr: name (v/c), pos (v/c), cooc (e/n)
+ edges from 89dee5c (vertex names):
[1] res ->cognosco tribunus ->miles bellum ->gero
[4] iter ->facio proelium ->committo fero ->possum
[7] bellum ->infero obses ->do legatus ->mitto
[10] res ->gero sustineo ->possum impetus ->facio
[13] castra ->educo locus ->castra consilium ->capio
[16] hostis ->impetus praesidium->relinquo pars ->flumen
[19] locus ->natura flumen ->transeo hostis ->castra
[22] signum ->do impero ->facio castra ->venio
+ ... omitted several edges
vertex_attr(co_occur_g)$name
[1] "res" "tribunus" "bellum" "iter" "proelium"
[6] "fero" "obses" "legatus" "sustineo" "impetus"
[11] "castra" "locus" "consilium" "hostis" "praesidium"
[16] "pars" "flumen" "signum" "impero" "summa"
[21] "aedificium" "cognosco" "miles" "gero" "facio"
[26] "committo" "possum" "infero" "do" "mitto"
[31] "educo" "capio" "relinquo" "natura" "transeo"
[36] "venio" "imperium" "incendo" "recipio" "copia"
$pos
[1] "NOUN" "NOUN" "NOUN" "VERB" "NOUN" "VERB" "VERB" "NOUN" "NOUN" "NOUN"
[11] "NOUN" "NOUN" "VERB" "VERB" "NOUN" "VERB" "NOUN" "VERB" "NOUN" "VERB"
[21] "VERB" "NOUN" "VERB" "NOUN" "VERB" "NOUN" "VERB" "VERB" "NOUN" "VERB"
[31] "NOUN" "NOUN" "VERB" "VERB" "VERB" "NOUN" "VERB" "NOUN" "NOUN" "NOUN"
Визуализируем!
# разными цветами закодирую анализируемые части речи
cols <- c('NOUN' = '#76EEC6', 'VERB' = '#CDC0B0')
set.seed(2026)
ggraph(co_occur_g, layout = 'fr', maxiter = 100) +
geom_edge_link(aes(width = cooc, edge_alpha = cooc)) +
geom_node_label(aes(label = name,
fill = pos),
colour = 'grey22',
size = 3) +
scale_fill_manual(values = cols) +
theme_graph(base_family = 'sans') +
theme(legend.position = 'bottom') +
labs(title = 'Коллокации в латинском датасете', subtitle = 'VERBs & NOUNs')Warning: The `trans` argument of `continuous_scale()` is deprecated as of ggplot2 3.5.0.
ℹ Please use the `transform` argument instead.