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

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

Я могу раскрашивать ветви своей дендрограммы с помощью пакета dendextend. Однако я не могу контролировать, какой цвет назначается какому идентификатору кластера. dendrextend назначает первый цвет первому найденному идентификатору кластера, независимо от того, является ли это идентификатором 1. Однако мне нужен идентификатор 1, окрашенный в цвет 1 и т. Д., Поскольку мне нужна легенда.

См. Этот пример. Мне нужна дендрограмма, которая раскрашивает метки и ветви _2 _-_ 3_ красным, _4 _-_ 5_ синим и _6 _-_ 7_ зеленым.

suppressPackageStartupMessages(library(dendextend))
library(dplyr)

set.seed(12346)
# Sample data: 
# ------------
# l = Leaf labels | g = assigned color of leaf | x = value for clustering
dat <- tibble(l = LETTERS[1:9],
              g = factor(rep(letters[1:3], each = 3)),
              x = round(runif(9,0,10)))

# color_branches() need integer cluster IDs
dat$gi <- dat$g %>% as.integer()

# Color IDs of each group
dat %>% distinct(g, gi)
## # A tibble: 3 x 2
##   g        gi
##   <fct> <int>
## 1 a         1
## 2 b         2
## 3 c         3
# ID 1 = red, ID 2 = blue, ID 3 = green
clucols <- c("red", "blue", "green")

# Clustering & Dendrogram
# -----------------------
dst <- dist(setNames(dat$x, dat$l))
den <- as.dendrogram(hclust(dst))
o <- order.dendrogram(den)

den <- den %>%
  color_branches(col = clucols, clusters = dat$gi[o]) 
# Transfer branch colors to labels
labels_colors(den) <- get_leaves_branches_col(den)

plot(den)

# Legend
dat %>% distinct(g, gi) %>%
{legend("topright", legend = .$g, col = clucols[.$gi], lty = 1)}

Результат:

Листья окрашены не в желаемом порядке, а по положению кластера на графике слева направо.

Дендрограмма с неправильной окраской

Если вы измените строку set.seed(...) на set.seed(12345), вы увидите, что окраска кажется правильной. Но это потому, что кластеры появляются в правильном порядке случайно, если смотреть слева направо:

Дендрограмма с правильной окраской

Как заставить color_branches() назначать цвета по идентификатору кластера, а не по тому, какой кластер идет первым?

Другие вопросы SO, которые я пробовал


person akraf    schedule 30.10.2018    source источник


Ответы (1)


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

Замените этот код в вопросе:

den <- den %>%
  color_branches(col = clucols, clusters = dat$gi[o]) 

с кодом ниже.

Вам нужно получить список, в котором есть каждый элемент для каждой группы. Каждый элемент, в свою очередь, содержит метки, которые вы хотите раскрасить, и сам цвет. Вы получите это, например, так:

library(purrr)
colmap <- dat %>% group_by(g) %>% summarise(l = list(l)) %>% transpose()
colmap

## [[1]]
## [[1]]$g
## [1] 1
## 
## [[1]]$l
## [1] "A" "B" "C"
## 
## 
## [[2]]
## [[2]]$g
## [1] 2
## 
## [[2]]$l
## [1] "D" "E" "F"
## 
## 
## [[3]]
## [[3]]$g
## [1] 3
## 
## [[3]]$l
## [1] "G" "H" "I"

Затем для каждого элемента примените branches_attr_by_labels. Поскольку он принимает дендрограмму и некоторые изменяющиеся параметры, а также возвращает дендрограмму, вы можете использовать purrr::reduce или base::Reduce:

den <- reduce(.x = colmap, .init = den, .f = function(d, m) 
  branches_attr_by_labels(d, m$l, clucols[m$g] ))

Как вариант, чуть длиннее:

for(e in colmap){
  den <- branches_attr_by_labels(den, e$l, clucols[e$g])
}

Результат для set.seed(123456). Сравните с изображением выше:

дендрограмма с правильной окраской

person akraf    schedule 01.11.2018