Работа по стилометрическому анализу текстов “Тихого Дона” и современной ему прозы с использованием метода консенсусных сетей. Цель работы — выявить стилистические связи между текстами и оценить положение спорных текстов (Dubia) относительно произведений М. Шолохова. Выполняется на основе датасета «Стилеметрические данные “Тихого Дона” и современной ему прозы», подготовленного Б.В. Ореховым.

library(dendextend)
library(stylo)
library(ape)
library(tidyverse)
library(ggsci)
library(phangorn)
library(TreeTools)
library(rgl) 
library(igraph)
library(ggraph)
library(philentropy)

# Читаем таблицу
don_df_raw <- read.table("table_with_frequencies.txt",
                         header = FALSE,
                         sep = "",
                         quote = "\"",
                         encoding = "UTF-8",
                         skip = 1,
                         row.names = 1)

# Устанавливаем заголовок из первой строки файла
first_line <- readLines("table_with_frequencies.txt", n = 1, encoding = "UTF-8")
colnames(don_df_raw) <- scan(text = first_line, what = character(), quiet = TRUE) |>
  gsub(pattern = '"', replacement = '', x = _)

don_df <- as.data.frame(t(don_df_raw)) |> scale()

Чтобы оценить материал, строим кластерную дендрограмму:

hc_complete <- hclust(dist(don_df), method = "complete")
plot(hc_complete)

и дендрограмму с использованием косинусного расстояния:

dist_mx <- don_df |> 
  philentropy::distance(method = "cosine", use.row.names = TRUE)
dist_mx <- as.dist(1 - dist_mx)
hc <- hclust(dist_mx)
plot(hc)

В качестве предикторов отбираем 100 из 500 наиболее вариативных слов. Это позволяет убрать шумовые признаки, сосредоточиться на словах, которые лучше разделяют тексты и ускорить вычисления без потери качества.

word_vars <- apply(don_df, 2, var, na.rm = TRUE)
top_words <- names(sort(word_vars, decreasing = TRUE)[1:500])
don_df_filtered <- don_df[, top_words]

Следующим этапом строим 100 деревьев (и выводим 4 из них для визуального сравнения). Каждое из 100 деревьев строится на основе случайной выборки из 100 слов (из отобранных 500). Закладываем seed для возможности повторить:

get_tree <- function(df) {
  X <- df[, sample(ncol(df), replace = FALSE, size = 100)]
  distmx <- dist(X, method = "manhattan")
  as.phylo(hclust(distmx))
}

set.seed(123)
trees_result <- map(1:100, ~get_tree(don_df_filtered))

walk(trees_result[1:4], plot)

par(mfrow = c(2, 2), mar = c(1, 1, 1, 1))

Строим из полученных деревьев финальный график - консенсусную сеть с порогом 0.3 (сплиты, встречающиеся не менее чем в 30% деревьев). (тоже не забываем заложить seed):

mph <- as.multiPhylo(trees_result)
cons.nw <- consensusNet(mph, prob = 0.3, rooted = FALSE)

# Цвета для авторов
cons.nw$author <- str_remove_all(cons.nw$tip.label, "_.+")
unique_authors <- unique(cons.nw$author)
n_authors <- length(unique_authors)

col_tbl <- tibble(
  label = unique_authors,
  col = pal_igv()(n_authors)
)

color_group <- tibble(label = cons.nw$author) |> 
  left_join(col_tbl, by = "label")

cons.nw$col <- color_group$col

# Открыть график в отдельном окне (для разных систем)
if(.Platform$OS.type == "windows") {
  windows(width = 16, height = 14)
} else if(Sys.info()["sysname"] == "Darwin") {
  quartz(width = 16, height = 14)
} else {
  x11(width = 16, height = 14)
}

set.seed(666)
par(mar = c(2, 2, 2.5, 2), oma = c(0, 0, 0, 0), family = "sans")

# Рисуем консенснусное дерево
plot(cons.nw, 
     type = "2D", 
     direction = "axial",
     use.edge.length = FALSE,
     font = 2,
     tip.color = cons.nw$col,
     edge.width = 1.0,
     cex = 0.8,
     label.offset = 0.05,
     main = "Консенсусная сеть: 'Тихий Дон' и современная проза")

# Добавляем подпись с параметрами
mtext(text = paste("100 деревьев | 100 случайных слов из 500 самых вариантивных | порог 0.3 | косинусное расстояние"),
      side = 1,
      line = 0.5,
      cex = 0.8,
      col = "darkgrey")

# Легенда
legend("bottomright",
       legend = unique_authors,
       fill = unique(cons.nw$col),
       border = NA,
       bty = "n",
       cex = 0.7,
       title = "Авторы")

Консенсусная сеть Наблюдения: Тексты чётко группируются по авторам. “Dubia_ТихийДон1-4” расположены недалеко от произведений Шолохова, что может свидетельствовать об их стилистической близости.