2017-03-01 3 views
2

Ich versuche, eine plotlyheatmap zu generieren, wo ich möchte, dass die Farben durch eine diskrete Skala angegeben werden.Verwenden von diskreten benutzerdefinierten Farbe in einer Plotly Heatmap

Hier ist, was ich meine:

Generieren von Daten mit zwei Clustern und sie hierarchisch gruppieren:

require(permute) 
set.seed(1) 
mat <- rbind(cbind(matrix(rnorm(2500,2,1),nrow=25,ncol=500),matrix(rnorm(2500,-2,1),nrow=25,ncol=500)), 
      cbind(matrix(rnorm(2500,-2,1),nrow=25,ncol=500),matrix(rnorm(2500,2,1),nrow=25,ncol=500))) 
rownames(mat) <- paste("g",1:50,sep=".") 
colnames(mat) <- paste("s",1:1000,sep=".") 
hc.col <- hclust(dist(t(mat))) 
dd.col <- as.dendrogram(hc.col) 
col.order <- order.dendrogram(dd.col) 
hc.row <- hclust(dist(mat)) 
dd.row <- as.dendrogram(hc.row) 
row.order <- order.dendrogram(dd.row) 
mat <- mat[row.order,col.order] 

Brems die Werte in mat zu Intervallen und eine Farbe für jedes Intervall eingestellt:

require(RColorBrewer) 
mat.intervals <- cut(mat,breaks=6) 
interval.mat <- matrix(mat.intervals,nrow=50,ncol=1000,dimnames=list(rownames(mat),colnames(mat))) 
interval.cols <- brewer.pal(6,"Set2") 
names(interval.cols) <- levels(mat.intervals) 

Mit ggplot2 zeichne ich diese heatmap auf diese Weise (auch mit der legend spezifizieren die diskrete Farben und entsprechende Bereiche):

require(reshape2) 
interval.df <- reshape2::melt(interval.mat,varnames=c("gene","sample"),value.name="expr") 
require(ggplot2) 
ggplot(interval.df,aes(x=sample,y=gene,fill=expr))+ 
    geom_tile(color=NA)+theme_bw()+ 
    theme(strip.text.x=element_text(angle=90,vjust=1,hjust=0.5,size=6),panel.spacing=unit(0.025,"cm"),legend.key=element_blank(),plot.margin=unit(c(1,1,1,1),"cm"),legend.key.size=unit(0.25,"cm"),panel.border=element_blank(),strip.background=element_blank(),axis.ticks.y=element_line(size=0.25))+ 
    scale_color_manual(drop=FALSE,values=interval.cols,labels=names(interval.cols),name="expr")+ 
    scale_fill_manual(drop=FALSE,values=interval.cols,labels=names(interval.cols),name="expr") 

die gibt: enter image description here

Dies ist mein Versuch, es mit plotly zu generieren:

plot_ly(z=mat,x=colnames(mat),y=rownames(mat),type="heatmap",colors=interval.cols) 

die gibt:

enter image description here

Die Figuren sind nicht identisch. In der Figur ggplot2 sind die Cluster im Gegensatz zur plotly Figur deutlich ausgeprägter.

Gibt es eine Möglichkeit, den plotly Befehl zu parametrisieren, um etwas ähnlicheres an die ggplot2 Zahl zu geben?

Ist es auch möglich, die plotly Legende diskret zu machen - ähnlich wie in der ggplot2 Abbildung?

Nun nehme ich an facet die Cluster. Im ggplot2 Fall würde ich tun:

require(dplyr) 
facet.df <- data.frame(sample=c(paste("s",1:500,sep="."),paste("s",501:1000,sep=".")),facet=c(rep("f1",500),rep("f2",500)),stringsAsFactors=F) 
interval.df <- left_join(interval.df,facet.df,by=c("sample"="sample")) 
interval.df$facet <- factor(interval.df$facet,levels=c("f1","f2")) 

Und dann Grundstück:

ggplot(interval.df,aes(x=sample,y=gene,fill=expr))+facet_grid(~facet,scales="free",space="free",switch="both")+ 
    geom_tile(color=NA)+labs(x="facet",y="gene")+theme_bw()+ 
    theme(strip.text.x=element_text(angle=90,vjust=1,hjust=0.5,size=6),panel.spacing=unit(0.05,"cm"),plot.margin=unit(c(1,1,1,1),"cm"),legend.key.size=unit(0.25,"cm"),panel.border=element_blank(),strip.background=element_blank(),axis.ticks.y=element_line(size=0.25))+ 
    scale_color_manual(drop=FALSE,values=interval.cols,labels=names(interval.cols),name="expr")+ 
    scale_fill_manual(drop=FALSE,values=interval.cols,labels=names(interval.cols),name="expr") 

Welche gibt: enter image description here

So werden die Cluster durch die panel.spacing getrennt sind, und suchen noch ausgeprägter. Gibt es eine Möglichkeit, diese Facettierung mit plotly zu erreichen?

+0

Was ist mit 'ggplotly' zu erscheinen? – Axeman

+0

Für diese Dimensionen die Umwandlung der ggplot zu plotly mit ggplotly dauert unvernünftig lang (viele viele Minuten) - nicht wirklich praktisch – dan

Antwort

1

Ich dachte anfangs das Gleiche, nämlich den Gradienten herunterzuspielen, aber stattdessen härtere Übergänge zu erzwingen scheint zumindest den Trick zu machen, die Farben deutlicher zu machen.

interval.cols2 <- rep(interval.cols, each=1000) 
plot_ly(z=mat,x=colnames(mat),y=rownames(mat),type="heatmap",colors=interval.cols2) 

enter image description here

+0

Vielen Dank @ R.S .. Irgendeine Idee, wie man facet? – dan

+0

Hmmnnn, ich bin nicht vertraut mit plot_ly Heatmap, aber in Heatmap.2 zum Beispiel können Sie Dummy NA Spalte oder Zeile Vektor hinzufügen, und legen Sie die Farbzuweisung für NA-Werte auf weiß, um ein Trennzeichen einzuführen. Angenommen, es gibt eine ähnliche Option in plot_ly, wenn dies ein Ergebnis eines Clusters ist, dann müssten Sie herausfinden, wo die Schnitte sind, oder wenn die Spaltenreihenfolge vorher bekannt ist, fügen Sie einfach einen NA-Vektor (oder eine Matrix) zwischen den 2 Gruppen. Sie müssen '' '' colnames auch einführen. – Djork

4

Lassen sie eine diskrete Farbkarte

df_colors = data.frame(range=c(0:11), colors=c(0:11)) 
color_s <- setNames(data.frame(df_colors$range, df_colors$colors), NULL) 
for (i in 1:12) { 
    color_s[[2]][[i]] <- interval.cols[[(i + 1)/2]] 
    color_s[[1]][[i]] <- i/12 - (i %% 2)/12 
} 

erhalten und einen schönen colorbar erhalten, indem ticktext Einstellung und drückt sie (len=0.2)

colorbar=list(tickmode='array', tickvals=c(1:6), ticktext=levels(mat.intervals), len=0.2) 

enter image description here Der gesamte Code, der

df_colors = data.frame(range=c(0:11), colors=c(0:11)) 
color_s <- setNames(data.frame(df_colors$range, df_colors$colors), NULL) 

for (i in 1:12) { 
    color_s[[2]][[i]] <- interval.cols[[(i + 1)/2]] 
    color_s[[1]][[i]] <- i/12 - (i %% 2)/12 
} 


plot_ly(z=c(interval.df$expr), x=interval.df$sample, y=interval.df$gene, colorscale = color_s, type = "heatmap", hoverinfo = "x+y+z", colorbar=list(tickmode='array', tickvals=c(1:6), ticktext=levels(mat.intervals), len=0.2)) 
1

Die Kombination der Antworten von @Maximilian Peters und @RS zu Ihrem Beispiel hinzugefügt werden muss:

Daten:

require(permute) 
set.seed(1) 
mat <- rbind(cbind(matrix(rnorm(2500,2,1),nrow=25,ncol=500),matrix(rnorm(2500,-2,1),nrow=25,ncol=500)), 
      cbind(matrix(rnorm(2500,-2,1),nrow=25,ncol=500),matrix(rnorm(2500,2,1),nrow=25,ncol=500))) 
rownames(mat) <- paste("g",1:50,sep=".") 
colnames(mat) <- paste("s",1:1000,sep=".") 
hc.col <- hclust(dist(t(mat))) 
dd.col <- as.dendrogram(hc.col) 
col.order <- order.dendrogram(dd.col) 
hc.row <- hclust(dist(mat)) 
dd.row <- as.dendrogram(hc.row) 
row.order <- order.dendrogram(dd.row) 
mat <- mat[row.order,col.order] 

Farben:

require(RColorBrewer) 
mat.intervals <- cut(mat,breaks=6) 
interval.mat <- matrix(mat.intervals,nrow=50,ncol=1000,dimnames=list(rownames(mat),colnames(mat))) 
require(reshape2) 
interval.df <- reshape2::melt(interval.mat,varnames=c("gene","sample"),value.name="expr") 
interval.cols <- brewer.pal(6,"Set2") 
names(interval.cols) <- levels(mat.intervals) 
interval.cols2 <- rep(interval.cols, each=ncol(mat)) 
color.df <- data.frame(range=c(0:(2*length(interval.cols)-1)),colors=c(0:(2*length(interval.cols)-1))) 
color.df <- setNames(data.frame(color.df$range,color.df$colors),NULL) 
for (i in 1:(2*length(interval.cols))) { 
    color.df[[2]][[i]] <- interval.cols[[(i + 1)/2]] 
    color.df[[1]][[i]] <- i/(2*length(interval.cols))-(i %% 2)/(2*length(interval.cols)) 
} 

Plot ting:

plot_ly(z=c(interval.df$expr),x=interval.df$sample,y=interval.df$gene,colors=interval.cols2,type="heatmap",colorscale=color.df, 
     colorbar=list(tickmode='array',tickvals=c(1:6),ticktext=names(interval.cols),len=0.2,outlinecolor="white",bordercolor="white",borderwidth=5,bgcolor="white")) 

enter image description here

Es wäre toll, wenn jemand hinzufügen:

  1. Wie eine schmale Grenze zwischen den Facetten Facette oder zu erstellen.
  2. Wie die colorbar Strichbeschriftungen bekommen genau in der Mitte jeder Box in der colorbar
+0

In Bezug auf (2) jetzt, dass @MaximilianPeters zeigte uns, wie man die Farbleiste hacken, können Sie von TickMode bis zu den anderen Parametern überprüfen, liest es scheint einen Hinweis darauf gibt es eine Möglichkeit, dies zu tun, indem TickMode auf "linear" und mit 0tick setzen und dtick, obwohl ich es nicht versucht habe. https://plot.ly/r/reference/#scatter-marker-colorbar-tickmode – Djork

+0

Ich spielte ein bisschen herum und scheiterte. Daher war mein Post auf jemanden mit Erfahrung ausgerichtet. Wenn es mir gelingt, es richtig zu machen, werde ich meine Antwort aktualisieren – dan

Verwandte Themen