Консенсусные деревья и сети

Автор

Авдеева Полина

Дата публикации

15.02.2026

Аннотация
Консенсусные деревья и сети для души

Установка пакетов

Перед началом работы необходимо скачать и подгрузить необходимые пакеты:

library(dendextend)
library(tidyverse)
library(ape)
library(ggsci)

Трансформация данных

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

После загрузки в среду R данные преобразуются в таблицу, которую затем необходимо привести к требуемому формату.

# Преобразование файла .txt в табличный формат
df <- read.table(
  "table_with_frequencies.txt",
  header = TRUE,
  sep = " ",
  check.names = FALSE,
  row.names = 1
)


# Транспорнировка таблицы
df_with_frequencies <- as.data.frame(t(df))

# Просмотр фрагмента таблицы
knitr::kable(df_with_frequencies [1:10, 1:10], caption = "Таблица частотности")
Таблица частотности
и в на не с а что он как то
Булгаков_БелаяГвардия 4.866468 3.347350 1.853296 1.494054 1.1473447 0.8800022 1.1779777 0.7894957 0.7059512 0.6516472
Булгаков_МастериМаргарита 4.398680 3.195690 1.758419 1.777723 1.1477107 0.8546409 1.6724286 1.0117052 0.7765474 0.9397540
Иванов_Бронепоезд1469 4.349652 2.207823 2.069834 1.715863 1.0679146 1.7278618 0.4259659 0.5579554 1.0439165 1.1339093
Иванов_ГолубыеПески 3.707162 2.702949 1.823978 1.637254 0.9176819 1.1977684 0.5077992 0.7264033 0.8061027 0.7651144
Крюков_ГруппаБ 4.318761 2.833192 1.559847 1.490874 1.4378183 0.6738115 0.7268676 0.6419779 0.6791171 0.4456706
Крюков_Зыбь 4.546693 2.371003 1.594295 1.944041 1.2400073 1.0265262 0.7539971 1.1991279 0.7948765 0.7994186
Крюков_КисточникуИсцелений 5.462529 2.546838 1.709602 1.176815 1.4402810 1.3348946 0.5620609 0.8957845 0.5737705 1.1416862
Крюков_Мать 4.038977 2.485525 1.786471 1.835899 1.3486796 0.8261545 0.8473379 0.7272984 0.9038271 0.7484819
Крюков_Шквал 4.433540 2.427374 1.459030 1.784706 1.0421642 0.8988666 1.3938947 1.0378219 0.9900560 0.8511008
Леонов_Барсуки 4.266004 2.556303 1.777759 1.826225 1.0497443 1.2198895 0.7991668 0.8631001 0.7960733 0.8795991

В результате преобразования таблица приняла корректную структуру: столбцы соответствуют переменным (словам), а ряды — наблюдениям (авторам и текстам). Можно переходить к следующему этапу анализа.

Построение консенсусного дерева

Меня заинтересовало построение танглграмм, позволяющих отслеживать различия между дендрограммами, полученными с использованием различных методов связи, при том что для кластеризации применялась одна и та же матрица расстояний (по умолчанию — евклидова, однако в нашем случае использовалась манхэттенская).

# Создаю матрицу попарных расстояний между объектами 
dist_matrix <- dist(df_with_frequencies, method = "manhattan")

# Строю танглграммы
d1 <- as.dendrogram(hclust(dist_matrix, method = "complete")) |>  
  set("labels_col", value = c("skyblue4", "darkolivegreen4", "sienna4", "plum4", "azure4"), k = 5)  |>  
  set("branches_k_color", value = c("skyblue4", "darkolivegreen4", "sienna4", "plum4", "azure4"), k = 5)

d2 <- as.dendrogram(hclust(dist_matrix, method = "single")) |>  
  set("labels_col", value = c("skyblue4", "darkolivegreen4", "sienna4", "plum4", "azure4"), k = 5)  |>  
  set("branches_k_color", value = c("skyblue4", "darkolivegreen4", "sienna4", "plum4", "azure4"), k = 5)

dlist <- dendlist(d1, d2)

# Строю график 
tanglegram(dlist, common_subtrees_color_lines = F, 
           highlight_distinct_edges  = T, 
           highlight_branches_lwd = F, 
           margin_inner = 8, 
           lwd = 0.6, 
           axes= F, 
           main_left = "Полное", 
           main_right = "Одиночное", 
           sort = T,
           lab.cex = 0.6)

Мне было интересно посмотреть на то, как группируются произведения в зависимости от метода связи. В данном случае, это полная связь ("complete") и одиночный метод ("single"). Данные методы выбраны в связи с тем, что они демонстрируют более корректную работу при использовании манхэттенского расстояния.

Для более детального выявления структурных различий каждая дендрограмма была разделена на пять кластеров (k = 5).

Комментарии

Итак, как можно кратко охарактеризовать полученный результат?

  1. Несмотря на использование разных методов связи, наблюдаются устойчивые тенденции: «Судьба человека» стабильно отделяется от остальных произведений Шолохова и формирует самостоятельный кластер.
  2. В полном методе по разным кластерам распределяются «Тихий Дон» и «Поднятая целина» Шолохова, в одиночном — все эти произведения находятся рядом. Тем не менее, «Тихий Дон» и «Донские рассказы» в обоих методах расположены по соседству. Это может говорить о сходстве их лексико-частотного профиля.
  3. Произведения Крюкова более компактно группируются дендраграмме с полным методом: там они все находятся в одном кластере. Это обосновывается тем, что полный метод лучше выявляет плотные авторские группы. При одиночной связи они распадаются, что может свидетельствовать о том, что такой метод сильнее реагирует на локальные сходства.

Как мне кажется, при выбранных параметрах метод полной связи демонстрирует более структурированное и интерпретируемое распределение произведений, поскольку формирует компактные и устойчивые кластеры.

Дополнение

Дополнительно хотелось бы построить обычное дерево, чтобы наглядно увидеть, как располагаются произведения

dist_matrix_new <- dist(df_with_frequencies, method = "manhattan")
hc <- hclust(dist_matrix_new, method = "complete")

phy_tree <- as.phylo(hc)

# Назначаю авторам цвета
palette_colors <- pal_simpsons()(9) # Цвета Симпсонов :)

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

# Строю дерево
par(mar = c(0,0,0,0))
plot.phylo(phy_tree,
           type = "tidy",
           use.edge.length = T,
           edge.width = 1,
           node.color = "grey60",
           font = 0.6,
           no.margin = T,
           label.offset = 0.1,
           node.depth = 1,
           tip.color = cols_df$color,
           cex = 0.5)

# Подписываю узлы
nodelabels(
  text = phy_tree$node.label,
  frame = "circle",
  bg = "white",
  cex = 0.5
)

Поскольку здесь также используется манхэттенское расстояние и кластеризация методом полной связи, наблюдаются сходства с предыдущим графиком.

  1. «Судьба человека» Шолохова, как и раньше, выделяется и стоит особняком от остальных произведений автора.
  2. «Тихий Дон» и «Донские рассказы» расположены близко друг к другу, тогда как «Поднятая целина» и «Они сражались за родину» стоят отдельно, но тоже относительно рядом.
  3. На этом графике цветами выделяются не кластеры, а авторы, поэтому более наглядно видно, что произведения каждого писателя в основном сгруппированы вместе. Это объясняется тем, что у каждого автора свой характерный стиль и язык. Наиболее неоднозначной в этом плане фигурой оказывается Шолохов, что ожидаемо.