简体   繁体   English

将ggplot树形图添加到绘图热图时控制共享图例

[英]Controlling the shared legend when adding a ggplot dendrogram plot to a plotly heatmap

I have genes x samples expression data I'd like to generate a plotly heatmap for and add the samples dendrogram ggplot to. 我有genes x samples表达数据我想生成一个plotly heatmap ,并将samples dendrogram ggplot添加到。

Here are my data: 这是我的数据:

set.seed(1)
mat <- matrix(rnorm(100*10),100,10,dimnames = list(paste0("G",1:100),paste0("S",1:10)))

Here's the clustering and dendrograms : 这是clusteringdendrograms

library(dendsort)
library(dplyr)

col.hc <- hclust(dist(t(mat))) %>% dendsort::dendsort(.)
col.dend <- as.dendrogram(col.hc)
col.ord <- order.dendrogram(col.dend)
row.hc <- hclust(dist(mat)) %>% dendsort::dendsort(.)
row.dend <- as.dendrogram(row.hc)
row.ord <- order.dendrogram(row.dend)
mat <- mat[row.ord,col.ord]

Here I'm creating a ggplot from col.dend , using dendextend . 在这里,我使用ggplotcol.dend创建一个dendextend Note that all legend associated text and ticks are suppressed: 请注意,所有与legend相关的textticks都被抑制:

library(dendextend)
library(ggplot2)

col.gg.dend <- dendextend::as.ggdend(col.dend)
col.gg.dend.ggplot <- ggplot(col.gg.dend,labels=F)+guides(fill=F)+theme_minimal()+
  theme(axis.title=element_blank(),axis.text=element_blank(),axis.ticks=element_blank(),panel.grid=element_blank(),legend.position="none",legend.text=element_blank(),legend.background=element_blank(),legend.key=element_blank())

And here I'm creating the plotly heatmap and adding col.gg.dend.ggplot using plotly::subplot : 在这里,我正在创建plotly heatmap并使用plotly::subplot plotly添加col.gg.dend.ggplot

library(plotly)
library(reshape2)
library(grDevices)

plot.df <- reshape2::melt(mat,varnames=c("gene","sample"),value.name="value")

heatmap.plot <- plot_ly(z=c(plot.df$value),x=plot.df$sample,y=plot.df$gene,colors=colorRamp(c("darkblue","white","darkred")),type="heatmap",colorbar=list(title="Expression",len=0.4)) %>%
  layout(yaxis=list(title="Gene"),xaxis=list(title="Sample"))

empty.axis <- list(showticklabels=F,showgrid=F,zeroline=F,title=NULL)
empty.plot <- plot_ly() %>% layout(margin=list(l=200),xaxis=empty.axis,yaxis=empty.axis)
subplot(plotly_build(col.gg.dend.ggplot),empty.plot,heatmap.plot,nrows=2,margin=c(0,0,0,0),heights=c(0.2,0.8),widths=c(0.8,0.2))

which gives me: 这给了我: 在此输入图像描述

All of this works nicely except for having the bottom part added to the heatmap legend (black,solid,1) and (NA,1) , which I'd like to remove/suppress. 除了将底部部分添加到heatmap legend (black,solid,1)(NA,1) ,所有这些(NA,1)我想删除/抑制。

Note that plotly_build(col.gg.dend.ggplot) draws the dendrogram without that legend part. 请注意, plotly_build(col.gg.dend.ggplot)绘制没有该legend部分的dendrogram

A relatively simple workaround is to do: 一个相对简单的解决方法是:

subplot(col.gg.dend.ggplot,
        plotly_empty(), 
        heatmap.plot,
        nrows = 2,
        margin = c(0,0,0,0),
        heights = c(0.2,0.8),
        widths = c(0.8,0.2)) %>%
  layout(showlegend = FALSE)

在此输入图像描述

The issue underlying is explained in this SO question . 在这个SO问题中解释了潜在的问题

layout options found later in the sequence of plots will override options found earlier in the sequence. 稍后在绘图序列中找到的布局选项将覆盖序列中先前找到的选项。

Since if you just reverse the order of the subplots. 因为如果你只是颠倒了子图的顺序。

subplot(heatmap.plot,
        plotly_empty(), 
        col.gg.dend.ggplot,
        nrows = 2,
        margin = c(0,0,0,0),
        heights = c(0.2,0.8),
        widths = c(0.8,0.2))

在此输入图像描述

the artifact is gone. 神器消失了。

If you manually specify the legend should not be plotted within heat-map the issue is gone: 如果您手动指定不应在热图中绘制图例,则问题就会消失:

subplot(col.gg.dend.ggplot,
        plotly_empty(),
        heatmap.plot %>%
          layout(showlegend = F),
        nrows = 2,
        margin = c(0, 0, 0, 0),
        heights = c(0.2, 0.8),
        widths = c(0.8, 0.2))

在此输入图像描述

and the colorbar has shifted towards the middle, indicating the heatmap plot had an invisible legend which triggered the legend of the dendogram to appear since it was later in the sequence of subplots. 并且颜色条向中间移动,表明热图图有一个不可见的图例,触发了树图的图例,因为它后面是子图的序列。

Do note that within subplot you need not call ggplotly or plotly_build on ggplot objects. 请注意,在subplot您无需在ggplot对象上调用ggplotlyplotly_build And an empty plot can be called by plotly_empty() . 并且plotly_empty()可以调用空图。

Another way to avoid the issue is to use ggdendro : 另一种避免问题的方法是使用ggdendro

library(ggdendro)
d.col <- dendro_data(col.dend)

col.2 <- ggplot() +
  geom_segment(data = d.col$segments, aes(x=x, y=y, xend=xend, yend=yend)) +
  labs(x = "", y = "") +
  theme_minimal() +
  theme(axis.text = element_blank(),
        axis.ticks = element_blank(),
        panel.grid = element_blank())

subplot(col.2,
        plotly_empty(), 
        heatmap.plot,
        nrows = 2,
        margin = c(0,0,0,0),
        heights = c(0.2,0.8),
        widths = c(0.8,0.2)) 

yielding the same plot as the first one posted. 产生与发布的第一个相同的情节。

The heatmaply package handles this nicely (disclaimer, I'm a contributor): hotmaply包处理得很好(免责声明,我是贡献者):

library(heatmaply)
set.seed(1)
mat <- matrix(rnorm(100*10),100,10,dimnames = list(paste0("G",1:100),paste0("S",1:10)))

heatmaply(mat, dendrogram="column", col = cool_warm, key.title = "Expression", plot_method = "plotly")

I did notice the same issue when not setting plot_method="plotly , though. 不过,当我没有设置plot_method="plotly ,我确实注意到了同样的问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM