ggtree: цветные ветки деревьев и наконечники

Уважаемое сообщество по переполнению стека,

Я хотел бы попросить вас помочь с моей проблемой. Я использую пакет ggtree для построения филогенетических деревьев, и я хотел бы показать на этих графиках больше информации, как это обычно бывает в статьях. Меня особенно интересует дерево с цветными ветвями (со смешанным градиентом), показывающее некоторые вариации непрерывного признака и некоторую точку на конце ветвей, указывающую цветом (или формой) дискретный признак. Хотя я могу делать и то, и другое по отдельности, мне совершенно не удалось объединить обе эти вещи в одном сюжете. Не могли бы вы помочь, пожалуйста?

Здесь я представляю вам воспроизводимый пример. Давайте получим это случайное дерево (tree.1) с девятью видами и некоторыми случайными длинами ветвей и эту случайную таблицу данных об этих видах (data1):

###STACK EXAMPLE

source("https://bioconductor.org/biocLite.R")
biocLite("ggtree")
library(ggtree)

tree.1<-read.tree(text="(spec1:2.2,((spec2:1.8,(spec9:1.4,(spec3:1.3,spec5:1.3):0.1):0.4):0.2,(spec8:1.7,(spec6:1.5,(spec7:1,spec4:1):0.5):0.2):0.3):0.2);")

data1<-data.frame(row.names = c("spec1","spec2","spec3","spec4","spec5","spec6","spec7","spec8","spec9"),
                  "tip" = c("spec1","spec2","spec3","spec4","spec5","spec6","spec7","spec8","spec9"),
                  "colour" = c("red", "red", "blue", "red", "red", "blue", "blue", "red", "blue"),
                  "fylo.signal" = c(0.1, 1.0, 0.3, 0.6, 0.2, 0.8, 0.7, 0.3, 0.6))

Если вы посмотрите на данные, вы увидите столбец цвета, который является моей дискретной переменной, и fylo.signal, который представляет собой случайную непрерывную переменную.

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

Я могу начать с ветвей цветового градиента. Перед нанесением данных на график есть небольшой черный ящик, но я думаю, что хоть немного понял, что он делает. Сначала я извлекаю только непрерывную переменную (b) и вычисляю узлы для своего дерева (a), а затем вычисляю свою непрерывную переменную для всех узлов, не являющихся вершинами, в моем дереве, то есть не только для конца. Затем я объединяю данные вместе.

b <- as.matrix(data1)[,3]
a <- data.frame(node = nodeid(tree.1, names(b)),
                signal = b)
fit2 <- phytools::fastAnc(tree.1,b,vars=TRUE,CI=TRUE)
c <- data.frame(node = names(fit2$ace), signal = fit2$ace)
d.1 <- rbind(a, c)
d.1$node <- as.numeric(d.1$node)
d.1$signal <- as.numeric(d.1$signal)

После этого я вставляю также дискретную переменную (и делаю внутренние узлы с NA для этого цвета):

colour.vector <- c(data1$colour, rep(NA, nrow(d.1)-nrow(data1)))
d.2 <- cbind(d.1, colour.vector)
d.2

... а затем вставляю эти данные в само филогенетическое древо:

tree.2 <- dplyr::full_join(tree.1, d.2, by = 'node')

Теперь о прорисовке. Я могу сделать цвет градиента ветвей, чтобы представить мою непрерывную переменную. Следующий код создает этот график:

## example1 (SEPARATE TREES)

t1 <- ggtree(tree.2, aes(color=signal), layout = 'circular', 
             ladderize = FALSE, continuous = TRUE, size=2) +
  ggplot2::scale_color_gradientn(colours=c('red', 'orange', 'green', 'cyan', 'blue')) +
  geom_tiplab(hjust = -.1, offset=.1) + 
  theme(legend.position = c(.05, .85))
t1

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

t2 <- ggtree(tree.2, layout = 'circular') + geom_tiplab(hjust = -.1, offset=.1) 
t2 <- t2 %<+% data1 + geom_tippoint(pch=16, size=4, aes(col=colour))
t2

Но когда я пытаюсь объединить эти два, возникает ошибка:

## example 1.5 (ERROR)

t3 <- t1 %<+% data1 + geom_tippoint(pch=16, size=4, aes(col=colour))
t3 ## Error: Discrete value supplied to continuous scale

Я думаю, когда функция aes используется при создании дерева, ее нельзя переопределить для частей графика? Я этого не понимаю. Мой лучший снимок - это следующий код:

## example 2 (WRONG ORDER OF COLOURS)
t4 <- ggtree(tree.2, aes(color=signal), layout = 'circular', 
             ladderize = FALSE, continuous = TRUE, size=2) +
  ggplot2::scale_color_gradientn(colours=c('red', 'orange', 'green', 'cyan', 'blue')) +
  geom_tiplab(hjust = -.1, offset=.1) + 
  theme(legend.position = c(.05, .85)) +
  geom_tippoint(pch=16, size=4, color=as.factor(colour.vector[1:9]))
t4

... что на самом деле делает это НЕПРАВИЛЬНОЕ изображение. Точки на концах ветвей окрашены, но не в соответствии с тем, что было в исходном наборе данных. Они следуют порядку в наборе данных, но не назначаются правильным видам. Виды были окрашены в соответствии с последовательностью из набора данных spec1 против часовой стрелки. Я не могу заставить ggtree фактически следовать за видами, как в моем втором графике выше, используя тот же код.

Кто-нибудь может помочь, пожалуйста?


person Ondra Kauzál    schedule 18.08.2020    source источник


Ответы (2)


Думаю, я нашел решение. Я просто отказываюсь от пакета ggtree и использую вместо него phytools. Намного меньше кода, гораздо больше элегантности. Если кому-то интересно, вот он (я просто поменял цвета исходного набора данных на breeding.range и соответствующие значения, порядок такой же):

library(phytools)

tree.1<-read.tree(text="(spec1:2.2,((spec2:1.8,(spec9:1.4,(spec3:1.3,spec5:1.3):0.1):0.4):0.2,(spec8:1.7,(spec6:1.5,(spec7:1,spec4:1):0.5):0.2):0.3):0.2);")

data1<-data.frame(row.names = c("spec1","spec2","spec3","spec4","spec5","spec6","spec7","spec8","spec9"),
                  "breeding.range" = c("tropical", "tropical", "temperate", "tropical", "tropical", "temperate", "temperate", "tropical", "temperate"),
                  "fylo.signal" = c(0.1, 1.0, 0.3, 0.6, 0.2, 0.8, 0.7, 0.3, 0.6))

var.cont<-setNames(data1[,2],rownames(data1))
var.disc<-setNames(data1[,1],rownames(data1))
var.disc<-as.factor(var.disc)
matrix.disc<-to.matrix(var.disc,levels(var.disc))
matrix.disc<-matrix.disc[tree.1$tip.label,]

obj<-contMap(tree.1,var.cont,plot=FALSE)

plotTree(tree.1,type="fan",ftype="i",offset=2,fsize=0.9)

plot(obj$tree,colors=obj$cols,type="fan",add=TRUE,ftype="off",lwd=3,
     xlim=get("last_plot.phylo",envir=.PlotPhyloEnv)$x.lim,
     ylim=get("last_plot.phylo",envir=.PlotPhyloEnv)$y.lim)

tiplabels(pie=matrix.disc,piecol=palette()[c(4,2)],cex=0.4)
person Ondra Kauzál    schedule 19.08.2020

(То, что я дал в качестве предыдущего ответа, теперь удаленного, на самом деле не то, что вы просили.)

Во-первых, быстрое исправление для создания d.1 без NA:

d.1 <- rbind(
    mutate(a, signal = as.numeric(signal)),
    c
)

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

cols <- sapply( # colour.vector, but with names of colours
    colour.vector,
    function(val)
        if (is.na(val))    NA
        else if (val == 1) 'blue'
        else               'red'
)
tiplabel_order <- as.numeric(gsub('spec', '', tree.2@phylo$tip.label))

t4 <- ggtree(tree.2, aes(color = signal), layout = 'circular', 
             ladderize = FALSE, continuous = TRUE, size = 2) +
  ggplot2::scale_color_gradientn(colours=c('red', 'orange', 'green', 'cyan', 'blue')) +
  geom_tiplab(hjust = -.1, offset=.1) + 
  theme(legend.position = c(.05, .85)) +
  geom_tippoint(pch=16, size=4, color=as.factor(cols[tiplabel_order]))
t4
person davnovak    schedule 19.08.2020