Как правильно покрасить края или правильно нарисовать ребра в R-дендрограмме? - PullRequest
8 голосов
/ 05 апреля 2009

Я сгенерировал эту дендрограмму , используя функции R * hclust(), as.dendrogram() и plot.dendrogram().

Я использовал функцию dendrapply() и локальную функцию для окраски листьев, которая работает нормально.

У меня есть результаты статистического теста, которые показывают, являются ли набор узлов ( например, кластер "_+v\_stat5a\_01_" и "_+v\_stat5b\_01_" в правом нижнем углу дерева) значительный или важный.

У меня также есть локальная функция, которую я могу использовать с dendrapply(), которая находит точный узел в моей дендрограмме, который содержит значительные листы.

Я бы хотел (следуя примеру):

  1. Раскрасить края, которые соединяют "_+v\_stat5a\_01_" и "_+v\_stat5b\_01_"; или
  2. Нарисуйте rect() вокруг "_+v\_stat5a\_01_" и "_+v\_stat5b\_01_"

У меня есть следующая локальная функция (детали условия «node-in-leafList-match-node-in-clusterList» не важны, но они выделяют важные узлы):

markSignificantClusters <<- function (n) {
  if (!is.leaf(n)) {
     a <- attributes(n)
     leafList <- unlist(dendrapply(n, listLabels))
     for (clusterIndex in 1:length(significantClustersList[[1]])) {
       clusterList <- unlist(significantClustersList[[1]][clusterIndex])
       if (nodes-in-leafList-match-nodes-in-clusterList) {
          # I now have a node "n" that contains significant leaves, and
          # I'd like to use a dendrapply() call to another local function
          # which colors the edges that run down to the leaves; or, draw
          # a rect() around the leaves
       }
     }
  }
}

Из этого блока if я пытался вызвать dendrapply(n, markEdges), но это не сработало:

markEdges <<- function (n) {
  a <- attributes(n)
  attr(n, "edgePar") <- c(a$edgePar, list(lty=3, col="red"))
}

В моем идеальном примере ребра, соединяющие "_+v\_stat5a\_01_" и "_+v\_stat5b\_01_", были бы пунктирными и красного цвета.

Я также пытался использовать rect.hclust() в этом if блоке:

ma <- match(leafList, orderedLabels)  
rect.hclust(scoreClusterObj, h = a$height, x = c(min(ma), max(ma)), border = 2)

Но результат не работает с горизонтальными дендрограммами (, т.е. дендрограммы с горизонтальными метками). Вот пример (обратите внимание на красную полосу в правом нижнем углу). Что-то не так с размерами того, что генерирует rect.hclust(), и я не знаю, как это работает, чтобы написать свою собственную версию.

Я ценю любой совет, чтобы заставить edgePar или rect.hclust() работать должным образом, или чтобы я мог написать свой собственный rect.hclust() эквивалент.

UPDATE

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

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

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

Это устраняет проблему отсечения, но вводит другую проблему в том, что пространство между концами краев кластера и метками листьев имеет ширину всего около шести пикселей, и я не контролирую это. Это ограничивает ширину вертикальной полосы.

Хуже всего то, что x -координата, которая отмечает, где вертикальная полоса может поместиться между двумя элементами, будет меняться в зависимости от ширины большего дерева (par["usr"]), что, в свою очередь, зависит от того, как дерево иерархия оказывается структурированной.

Я написал «исправление» или, лучше сказать, хак, чтобы скорректировать это значение x и ширину rect для горизонтальных деревьев. Это не всегда работает согласованно, но для деревьев, которые я создаю, кажется, не дают слишком близко (или накладываются) края и метки.

В конечном счете, лучшим решением было бы выяснить, как нарисовать rect, чтобы не было отсечения. Или последовательный способ вычисления конкретной позиции x между краями дерева и метками для любого данного дерева, чтобы правильно расположить по центру и размеру полосы.

Меня также очень заинтересовал бы метод аннотирования кромок цветами или стилями линий.

1 Ответ

2 голосов
/ 09 апреля 2009

Итак, вы фактически задали около пяти вопросов (5 +/- 3). Что касается написания вашей собственной функции, подобной rect.hclust, источник находится в library/stats/R/identify.hclust.R, если вы хотите посмотреть на нее.

Я быстро взглянул на него и не уверен, что он делает то, что думал, прочитав ваше описание - кажется, он рисует несколько прямоугольников. Также появляется селектор x быть жестко запрограммированным для разделения тегов по горизонтали (это не то, что вы хотите, и нет y).

Я вернусь, но тем временем вы можете (помимо просмотра источника) попробовать сделать несколько rect.hclust с разными цветами border= и разными значениями h=, чтобы увидеть, появляется ли шаблон ошибки.

Обновление

Мне тоже не везло на это.

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

Другой идеей было бы заполнить прямоугольник полупрозрачным (с низким альфа) цветом, создавая затененную область, а не ограничивающую рамку.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...