Создание дендрограмм вручную: как исправить «матрица слияния имеет недопустимое содержимое» в plot.hclust? - PullRequest
1 голос
/ 27 октября 2019

Я создаю объект hclust вручную (т.е. создаю список с необходимыми слотами, затем меняю его класс на hclust). Шаблон слияния, высоты бифуркаций, упорядочение листовых узлов и метки листовых узлов известны. Моя цель (и средства тестирования) - построить результирующую дендрограмму. Я не могу создать печатный объект hclust с моими параметрами.

Компоненты объекта hclust описаны в документации по hclust функции здесь (см. Раздел Значение ).

Ниже приведен воспроизводимый фрагмент кода R, который я использую для генерации и построения дендрограммы.

tree <- list()
tree$merge <- matrix(c( -1,  -7,  # row  1
                        -2,  -6,  # row  2
                        -3, -12,  # row  3
                        -4, -14,  # row  4
                        -5,  -8,  # row  5
                        -9, -11,  # row  6
                       -13, -20,  # row  7
                       -15, -19,  # row  8
                         1,   8,  # row  9
                         2,   5,  # row 10
                         3,   6,  # row 11
                         2, -18,  # row 12
                         1,   3,  # row 13
                         2,   4,  # row 14
                       -10,   7,  # row 15
                       -16, -17,  # row 16
                         1,   2,  # row 17
                        15,  16,  # row 18
                         1,  15), # row 19
                     ncol = 2,
                     byrow = TRUE)
tree$height <- c(0.06573653, 0.06573653, 0.06573653, 0.06573653, 0.06573653, 0.06573653, 0.06573653, 0.06573653, 0.11167131, 0.11167131, 0.11167131, 0.12832304, 0.17304035, 0.17304035, 0.17304035, 0.17304035, 0.22965349, 0.22965349, 0.23334799)
tree$labels <- as.character(1:20)
tree$order <- c(1, 7, 15, 19, 3, 12, 9, 11, 2, 6, 5, 8, 18, 4, 14, 13, 20, 10, 16, 17)
class(tree) <- "hclust"
plot(tree)

Каждая строка матрицы tree$mergeсоответствует бифуркации. Отрицательные целые числа относятся к индексам конечных узлов, в то время как положительные целые относятся к существующим кластерам по индексам строк в tree$merge.

Запуск кода приводит к следующему сообщению об ошибке.

Error in plot.hclust(tree) : 'merge' matrix has invalid contents

Эскиз предполагаемого результата показан ниже со значениями heights, отмеченными дополнительными пунктирными линиями. (Чертеж не в масштабе.)

Intended dendrogram

1 Ответ

1 голос
/ 28 октября 2019

Действительность дерева hclust проверяется функцией .validity.hclust. Его исходный код указан здесь . Посмотрите на строки 121-135.

То, что вы получили ошибку, означает, что ваше дерево недопустимо из-за его merge матрицы. Он имеет неуникальные элементы (например, 1 и 2). В правильно построенной матрице merge все записи уникальны и варьируются от -N_obs до N_obs-2 (без учета нуля), где N_obs - это (положительное) число наблюдений. Это проверяется следующим if тестом в коде:

if(identical(sort(as.integer(merge)), c(-(n:1L), +seq_len(n-2L))))
    TRUE
else
    "'merge' matrix has invalid contents"

Из ссылки hclust:

слияние a n -Матрица 1 на 2.

Строка i слияния описывает слияние кластеров на этапе i кластеризации. Если элемент j в строке отрицателен, то наблюдение - j было объединено на этом этапе. Если j положительно, то слияние было с кластером, сформированным на (более ранней) стадии j алгоритма. Таким образом, отрицательные записи в слиянии указывают на агломерации синглетонов, а положительные записи указывают на агломерации не-синглетонов.

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

Итак, пересмотрите ваш hclust объект. Вот некоторый код, чтобы дать вам представление о том, как выглядит правильный hclust объект:

iris2 <- iris[1:20,-5]
species_labels <- iris[,5]
d_iris <- dist(iris2)
tree_iris <- hclust(d_iris, method = "complete")

. Более подробно рассмотрим tree_iris$merge.

ОБНОВЛЕНИЕ

После того, как у меня появилось больше времени, я решил исправить ваш код. Я изменил merge запись tree. Вот как выглядит рабочий код, который воспроизводит вашу дендрограмму:

tree <- list()
tree$merge <- matrix(c( -1,  -7,  # row  1
                        -2,  -6,  # row  2
                        -3, -12,  # row  3
                        -4, -14,  # row  4
                        -5,  -8,  # row  5
                        -9, -11,  # row  6
                        -13, -20,  # row  7
                        -15, -19,  # row  8
                        1,   8,  # row  9: 1,7,15,19
                        2,   5,  # row 10: 2,6,5,8
                        3,   6,  # row 11: 3,12,9,11
                        10, -18,  # row 12: 2,6,5,8 + 18
                        9,   11,  # row 13:  1,7,15,19 + 3,12,9,11
                        12,   4,  # row 14: row 12 + row 4
                        -10,   7,  # row 15: row 7 + 10
                        -16, -17,  # row 16
                        13,   14,  # row 17: row 13 + row 14 
                        15,  16,  # row 18: row 15 + row 16
                        17,  18), # row 19: row 17 + row 18
                     ncol = 2,
                     byrow = TRUE)
tree$height <- c(0.06573653, 0.06573653, 0.06573653, 0.06573653, 0.06573653, 0.06573653, 0.06573653, 0.06573653, 0.11167131, 0.11167131, 0.11167131, 0.12832304, 0.17304035, 0.17304035, 0.17304035, 0.17304035, 0.22965349, 0.22965349, 0.23334799)
tree$labels <- as.character(1:20)
tree$order <- c(1, 7, 15, 19, 3, 12, 9, 11, 2, 6, 5, 8, 18, 4, 14, 13, 20, 10, 16, 17)
class(tree) <- "hclust"
plot(tree)
...