Визуализация данных о совместной встречаемости слов у Цезаря

Autor:in

Ксения Дмитриева

Veröffentlichungsdatum

8. März 2026

Zusammenfassung
Meow-meow

Начало работы и данные

Для работы используем следующие библиотеки:

library(tidyverse)
library(ggraph)
library(igraph)
library(ggimage)
library(visNetwork)
library(udpipe)

Загрузим данные:

caesar <- udpipe_read_conllu("https://github.com/locusclassicus/text_analysis_2024/raw/main/files/bg_latinpipe.conllu")

Из всех токенов оставим только существительные:

caesar_subset <-  caesar |> 
  filter(upos == "NOUN")

Совместная встречаемость существительных

Используем функцию из пакета udpipe, чтобы найти существительные, которые встречаются вместе больше тридцати раз:

cooc <- cooccurrence(caesar_subset, term = "lemma", 
                     group = c("doc_id", "sentence_id")) |>
  as_tibble() |> 
  filter(cooc > 30)

cooc
# A tibble: 30 × 3
   term1  term2   cooc
   <chr>  <chr>  <dbl>
 1 castra hostis    92
 2 castra locus     67
 3 castra dies      59
 4 hostis locus     58
 5 hostis res       57
 6 flumen pars      49
 7 castra legio     47
 8 locus  pars      47
 9 hostis miles     46
10 castra pars      46
# ℹ 20 more rows

Визуализируем результат при помощи интерактивного графа:

cooc_g <- graph_from_data_frame(cooc)
data <- toVisNetworkData(cooc_g)

#для наглядности закодируем цветом ребер данные о совместной встречаемости
data$edges <- data$edges |>
  mutate(color = case_when(
    cooc >= 30 & cooc <= 40 ~ "lightgreen",
    cooc >= 41 & cooc <= 50 ~ "green",
    cooc > 50 ~ "black"))

#зададим форму узлов box, чтобы текст помещался внутри узла и лучше читался
data$nodes$shape <- "box"

#создадим объект visNetwork
cooc_3d <- visNetwork(nodes = data$nodes, 
                      edges = data$edges,
                      width = "100%", 
                      height = 600)

Интерактивный граф

visOptions(cooc_3d, 
           highlightNearest = list(enabled = TRUE, degree = 1, hover = TRUE), 
           nodesIdSelection = FALSE)  |> 
  visPhysics(maxVelocity = 20, stabilization = FALSE)  |>  
  visInteraction(dragNodes = TRUE) |>
  visNodes(labelHighlightBold = TRUE, 
           borderWidth = 0, 
           color = list(background = "pink", hover = 'red'), 
           font = list(color = "black", size = 13)) |>
  visEdges(width = 2.8) |>
  visLegend(position = 'right',
            main = 'Cooccurrence',
    addEdges = data.frame(
      label = c("30-40", 
                "41-50", 
                ">50"),
      color = c("lightgreen", "green", "black"),
      width = c(2.8, 2.8, 2.8)
    ))