Анализ авторства Тихого Дона методом консенсунсных деревьев

Autor:in

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

Veröffentlichungsdatum

15. Februar 2026

Zusammenfassung
Meow-meow

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

Для работы используется файл с частотностями слов из датасета «Стилеметрические данные “Тихого Дона” и современной ему прозы», подготовленного Б.В. Ореховым.

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

library(tidyverse)
library(philentropy)
library(dendextend)
library(stylo)
library(phangorn)
library(ggraph)
library(ggsci)

Считаем данные из файла и преобразуем в датафрейм, причем исходные строки и столбцы поменяем местами, чтобы в столбцах оказались слова, а в строках - наблюдения:

path <- 'table_with_frequencies.txt'

table <- read.table(path)

table_with_freqs <- table |>
  as.data.frame.matrix() |>
  t()

Подготовительная работа с деревьями

Для создания консенсусного дерева потребуется много отдельных деревьев. Создадим функцию get_tree(df), которая будет создавать дерево на основе выборки из 500 переменных (всего в нашем датафрейме 5000 переменных). Будем использовать манхэттэнское расстояние и метод полносвязной кластеризации (complete linkage):

get_tree <- function(df) {
  X <- df[ , sample(5000, replace = FALSE, size = 500)]

  dist_mx <- dist(X, method = "manhattan")

  res_tree <- as.phylo(hclust(dist_mx, method ="complete"))
}

Используем итератор, чтобы создать 400 деревьев, на основе которых будем строить консенсусное дерево:

set.seed(123)

trees_result <- map(1:400, ~get_tree(table_with_freqs))

Посмотрим на пример того, как выглядят получившиеся деревья, с которыми мы будем работать:

par(mfrow = c(2, 2), mar = c(0,0,0,0))
walk(trees_result[1:4], plot)

Создание консенсусного дерева и график

Строим консенсусное дерево:

set.seed(123)

cons <- consensus(trees_result, p = 0.4, rooted = TRUE)

Для последующего оформления графика присваиваем уникальный цвет каждому автору:

cols <- pal_igv()(12)
cols <- tibble(author = str_remove(cons$tip.label, "_.+")) |> 
  mutate(color = case_when(author == "Булгаков"  ~ cols[1],
                           author == "Иванов" ~ cols[2],
                           author == "Крюков"  ~ cols[3],
                           author == "Леонов" ~ cols[4],
                           author == "Островский"  ~ cols[5],
                           author == "Платонов" ~ cols[6],
                           author == "Севский" ~ cols[7],
                           author == "Серафимович" ~ cols[8],
                           author == "Фадеев" ~ cols[9],
                           author == "Фурманов" ~ cols[10],
                           author == "Шолохов" ~ cols[11],
                           author == "Dubia" ~ cols[12]))

Строим график и подписываем узлы:

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

plot.phylo(cons, 
           type = "fan", 
           use.edge.length = TRUE,
           edge.width = 1, 
           node.color = "grey30",
           font = 1, 
           no.margin = FALSE, 
           label.offset = 0.1,
           direction = "rightwards", 
           plot = TRUE, 
           lab4ut = "a",
           node.depth = 3, 
           tip.color = cols$color,
           cex = 0.7)

# подписываем узлы
nodelabels(text=sprintf("%.2f", cons$node.label),
           node=1:cons$Nnode+Ntip(cons),
           frame="circle",
           bg = "white",
           cex = 0.4, 
)

Краткий комментарий

Мы видим, что произведения Шолохова попадают в два разных кластера (кроме рассказа Судьба человека, который оказывается отдельно). Для нас важно, что Тихий Дон оказывается в тех же двух кластерах, что и другие произведения Шолохова, и не смешивается с произведениями других авторов. В то же время другие авторы оказываются в основном каждый в своем кластере. Отдельно стоит отметить, что Тихий Дон стоит отдельно от произведений Крюкова, которого некоторые исследователи считают настоящим автором этого романа.