Подтвердить что ты не робот

Ориентация диагональных меток по оси х в тепловой карте (-ях)

Создание тепловых карт в R было предметом многих сообщений, обсуждений и итераций. Моя основная проблема заключается в том, что сложно сочетать визуальную гибкость решений, доступных в решетке levelplot() или базовой графике image(), с легкой кластеризацией базовых heatmap(), pheatmap pheatmap() или gplots 'heatmap.2(). Это крошечная деталь, которую я хочу изменить - диагональную ориентацию меток на оси х. Позвольте мне показать вам свою точку зрения в коде.

#example data
d <- matrix(rnorm(25), 5, 5)
colnames(d) = paste("bip", 1:5, sep = "")
rownames(d) = paste("blob", 1:5, sep = "")

Вы можете легко изменить ориентацию по диагонали с помощью levelplot():

require(lattice)
levelplot(d, scale=list(x=list(rot=45)))

enter image description here

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

Теперь, переходя к действительным связанным функциям heatmap(), кластеризация и все базовые визуальные эффекты суперпросты - почти не требуется настройка:

heatmap(d)

enter image description here

и так далее:

require(gplots)
heatmap.2(d, key=F)

enter image description here

и, наконец, мой любимый:

require(pheatmap)
pheatmap(d) 

enter image description here

Но у всех из них нет возможности повернуть метки. Руководство для pheatmap предполагает, что я могу использовать grid.text для настройки моих меток. Какая радость - особенно при кластеризации и изменении порядка отображения ярлыков. Если я не пропущу что-то здесь...

Наконец, есть старый хороший image(). Я могу повернуть метки, в общем, это "наиболее настраиваемое решение, но не кластеризация".

image(1:nrow(d),1:ncol(d), d, axes=F, ylab="", xlab="")
text(1:ncol(d), 0, srt = 45, labels = rownames(d), xpd = TRUE)
axis(1, label=F)
axis(2, 1:nrow(d), colnames(d), las=1)

enter image description here

Итак, что мне делать, чтобы получить мою идеальную, быструю карту тепла, с кластеризацией и ориентацией и приятными визуальными функциями взлома? Моя лучшая ставка меняет heatmap() или pheatmap() так или иначе, потому что эти два, кажется, наиболее универсальны в настройке. Но любые решения приветствуются.

4b9b3361

Ответ 1

Чтобы исправить pheatmap, все, что вы действительно хотите сделать, это войти в pheatmap:::draw_colnames и настроить несколько настроек в своем вызове grid.text(). Здесь один из способов сделать это, используя assignInNamespace(). (Возможно, вам потребуются дополнительные настройки, но вы получите изображение;):

library(grid)     ## Need to attach (and not just load) grid package
library(pheatmap)

## Your data
d <- matrix(rnorm(25), 5, 5)
colnames(d) = paste("bip", 1:5, sep = "")
rownames(d) = paste("blob", 1:5, sep = "")

## Edit body of pheatmap:::draw_colnames, customizing it to your liking
draw_colnames_45 <- function (coln, ...) {
    m = length(coln)
    x = (1:m)/m - 1/2/m
    grid.text(coln, x = x, y = unit(0.96, "npc"), vjust = .5, 
        hjust = 1, rot = 45, gp = gpar(...)) ## Was 'hjust=0' and 'rot=270'
}

## For pheatmap_1.0.8 and later:
draw_colnames_45 <- function (coln, gaps, ...) {
    coord = pheatmap:::find_coordinates(length(coln), gaps)
    x = coord$coord - 0.5 * coord$size
    res = textGrob(coln, x = x, y = unit(1, "npc") - unit(3,"bigpts"), vjust = 0.5, hjust = 1, rot = 45, gp = gpar(...))
    return(res)}

## 'Overwrite' default draw_colnames with your own version 
assignInNamespace(x="draw_colnames", value="draw_colnames_45",
ns=asNamespace("pheatmap"))

## Try it out
pheatmap(d)

введите описание изображения здесь

Ответ 2

Это немного сложнее, чем мой комментарий, потому что heatmap разбивает область построения, чтобы рисовать дендрограммы, а последний участок графика - это не график image, к которому вы хотите прикреплять метки.

Существует решение, хотя heatmap предоставляет аргумент add.expr, который принимает выражение, которое будет оцениваться при рисовании image. Также необходимо знать переупорядочение меток, которые происходят из-за заказа дендрограмм. Последний бит включает немного неэлегантного взлома, поскольку я сначала нарисую карту нагрева, чтобы получить информацию о переупорядочении, а затем используйте ее, чтобы правильно нарисовать тепловую карту с помощью угловых меток.

Сначала пример из ?heatmap

 x  <- as.matrix(mtcars)
 rc <- rainbow(nrow(x), start = 0, end = .3)
 cc <- rainbow(ncol(x), start = 0, end = .3)
 hv <- heatmap(x, col = cm.colors(256), scale = "column",
               RowSideColors = rc, ColSideColors = cc, margins = c(5,10),
               xlab = "specification variables", ylab =  "Car Models",
               main = "heatmap(<Mtcars data>, ..., scale = \"column\")")

На этом этапе метки не так, как мы хотим их, но hv содержит информацию, которая нам нужна, чтобы изменить порядок colnames mtcars в его компоненте $colInd:

> hv$colInd
 [1]  2  9  8 11  6  5 10  7  1  4  3

Вы используете это, как и вывод из order например:

> colnames(mtcars)[hv$colInd]
 [1] "cyl"  "am"   "vs"   "carb" "wt"   "drat" "gear" "qsec" "mpg"  "hp"  
[11] "disp"

Теперь используйте это для создания меток, которые мы хотим, в правильном порядке:

 labs <- colnames(mtcars)[hv$colInd]

Затем мы повторно вызываем heatmap, но на этот раз мы указываем labCol = "" для подавления пометок переменных столбца (используя строки с нулевой длиной). Мы также используем вызов text для рисования меток под нужным углом. Вызов text:

text(x = seq_along(labs), y = -0.2, srt = 45, labels = labs, xpd = TRUE)

который по сути является тем, что у вас есть в вашем вопросе. Играйте со значением y, поскольку вам нужно отрегулировать его по длине строк, чтобы метки не пересекались с графиком image. Мы указываем labels = labs, чтобы передать метки, которые мы хотим провести, в требуемом порядке. Весь вызов text передается add.expr без кавычек. Вот весь вызов:

 hv <- heatmap(x, col = cm.colors(256), scale = "column",
               RowSideColors = rc, ColSideColors = cc, margins = c(5,10),
               xlab = "specification variables", ylab =  "Car Models",
               labCol = "",
               main = "heatmap(<Mtcars data>, ..., scale = \"column\")",
               add.expr = text(x = seq_along(labs), y = -0.2, srt = 45,
                               labels = labs, xpd = TRUE))

Результат:

enter image description here

Ответ 3

Я также ищу метод для поворота текста меток с помощью тепловой карты. В конце концов мне удалось найти это решение:

library(gplots)

library(RColorBrewer)

heatmap.2(x,col=rev(brewer.pal(11,"Spectral")),cexRow=1,cexCol=1,margins=c(12,8),trace="none",srtCol=45)

Ключевым аргументом является srtCol(or srtRow for row labels), который используется для поворота меток столбцов в gplots.

Ответ 4

Решение с использованием lattice::levelplot и latticeExtra::dendrogramGrob:

library(lattice)
library(latticeExtra)

Данные примера:

d <- matrix(rnorm(25), 5, 5)
colnames(d) = paste("bip", 1:5, sep = "")
rownames(d) = paste("blob", 1:5, sep = "")

Вы должны определить дендрограммы для строк и столбцов (вычисленные внутри heatmap):

dd.row <- as.dendrogram(hclust(dist(d)))
row.ord <- order.dendrogram(dd.row)

dd.col <- as.dendrogram(hclust(dist(t(d))))
col.ord <- order.dendrogram(dd.col)

и передать их функции dendrogramGrob в legend аргумент levelplot.

Я определил новую тему с цветами от RColorBrewer и изменили ширину и цвет границ ячеек с помощью border и border.lwd:

myTheme <- custom.theme(region=brewer.pal(n=11, 'RdBu'))

levelplot(d[row.ord, col.ord],
          aspect = "fill", xlab='', ylab='',
          scales = list(x = list(rot = 45)),
          colorkey = list(space = "bottom"),
          par.settings=myTheme,
          border='black', border.lwd=.6,
          legend =
          list(right =
               list(fun = dendrogramGrob,
                    args =
                    list(x = dd.col, ord = col.ord,
                         side = "right",
                         size = 10)),
               top =
               list(fun = dendrogramGrob,
                    args =
                    list(x = dd.row,
                         side = "top"))))

levelplot with dendrogram

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

levelplot(d[row.ord, col.ord],
          aspect = "fill", xlab='', ylab='',
          scales = list(x = list(rot = 45)),
          colorkey = list(space = "bottom"),
          par.settings=myTheme,
          border='black', border.lwd=.6,
          shrink=c(.75, .95),
          legend =
          list(right =
               list(fun = dendrogramGrob,
                    args =
                    list(x = dd.col, ord = col.ord,
                         side = "right",
                         size = 10)),
               top =
               list(fun = dendrogramGrob,
                    args =
                    list(x = dd.row,
                         side = "top"))))

levelplot with dendrogram and scaled cell sizes

Ответ 5

Я смог отвезти Гэвина Симпсона и немного подрезал его для работы для простых целей прототипирования, где data1 - это объект read.csv() и data1_matrix, конечно, матрица, созданная из этого

heatmap(data_matrix, Rowv=NA, Colv=NA, col=heat.colors(64), scale='column', margins=c(5,10),
   labCol="", add.expr = text(x = seq_along(colnames(data1)), y=-0.2, srt=45, 
   labels=colnames(data1), xpd=TRUE))

Boom! Спасибо, Гэвин.

Ключевым битом для этого является часть до бит add.expr, где он устанавливает labCol в значение "", что необходимо для предотвращения перекрытия первых (прямых) меток с новыми 45 градусами