talgalili / heatmaply

Interactive Heat Maps for R Using plotly
378 stars 73 forks source link

Rowsidecolors/Colsidecolors in the style of heatmap.2 #21

Closed alanocallaghan closed 8 years ago

alanocallaghan commented 8 years ago

It would be very useful to have Rowsidecolors and Colsidecolors (eg, http://manuals.bioinformatics.ucr.edu/home/R_BioCondManual/hclust3.png).

I have had a look through plotly's R API and haven't been able to find a good way to do categorical heatmap style plots in plotly natively. A possible solution would be to use ggplotly() though this is not ideal due to speed and mixing interfaces. I would be happy to work on this and submit a pull request if a potential solution can be worked out

talgalili commented 8 years ago

Hi @Alanocallaghan. This is something I would like to add (and wanted to for a while, but didn't get to it). Since heatmaply is based on ggplotly and subplot, I believe the way to do it is by creating a stacked bar chart of the extra elements, and create a dedicated subplot layout for when this parameter is supplied. What do you think?

talgalili commented 8 years ago

On a second thought, it could probably also be done using geom_tile. I would check how visdat does it.

alanocallaghan commented 8 years ago

Hi Tal, visdat uses geom_raster which is simply a special case of geom_tile. I think this would be the most sensible way to do it. Unfortunately, I don't know of a native plotly equivalent for geom_tile. The vis_dat_ly function (plotly equivalent) seems to use the heatmap trace so perhaps it is possible to make categorical heatmaps in this way.

However if you're happy using ggplotly rather than native plotly commands, that should simplify matters a bit. I'll try to get a working prototype today some time. Cheers

talgalili commented 8 years ago

:+1:

alanocallaghan commented 8 years ago

Hi Tal,

I have put together some working code on my fork (https://github.com/Alanocallaghan/heatmaply). It currently requires a "molten" data.frame as might be produced by reshape2::melt. As you'll see, the subplot layout code gets much more complex with the possibility that colsidecolours, rowsidecolours, column dendrogram and row dendrogram can all be present or absent, so I re-organised that code to reduce repitition. I'd probably like to test this a bit more thoroughly before submitting a PR but I think I've covered everything in a sensible way.

Example: https://jsfiddle.net/cetgn1pb/

talgalili commented 8 years ago

Very nice work @Alanocallaghan ! I will wait for you to finish tightening up the code before a more proper review.

One small note - maybe it would be better to use something like colorspace:rainbow_hcl as default instead of viridis for colors, since often the values there would be categorical (and of course, the user could use viridis if they would like). What do you think?

alanocallaghan commented 8 years ago

Hi Tal, right you are. I simply used viridis as a placeholder before choosing a more suitable default palette. Cheers Alan

talgalili commented 8 years ago

:+1: Exciting stuff.

talgalili commented 8 years ago

Hi @Alanocallaghan First, beautiful work! Second, I found two more bugs. This time in col_side_colors.

Example code:


x  <- as.matrix(datasets::mtcars)
rc <- colorspace::rainbow_hcl(nrow(x))

library(heatmaply)

heatmaply(x[,-c(8,9)], seriate = "mean",
          col_side_colors = c(rep(0,5), rep(1,4)),
          row_side_colors = x[,8:9])
heatmaply(x[,-c(8,9)], seriate = "mean",
          col_side_colors = data.frame(a=c(rep(0,5), rep(1,4))),
          row_side_colors = x[,8:9])

The first call produce a heatmaply in which the tooltip doesn't work when hovering over it:

image

The second call results in the following error:

Error in heatmapr(x, row_side_colors = row_side_colors, col_side_colors = col_side_colors, : col_side_colors and x have different numbers of columns

Also, (not a bug, just wondering) do you think it is possible to also include a sidebar legend of the row_side_colors when it is used?

p.s.: please see that the details I added about you in the DESCRIPTION are accurate. If not, please fix as you see fit.

Cheers, Tal

alanocallaghan commented 8 years ago

Hi Tal,

I'll work on those errors. As for the legend, I had considered trying to put a legend of some sort into the plotly_empty() panels, but haven't gotten around to sketching it out yet

alanocallaghan commented 8 years ago

Okay, the second error is somewhat intentional; The idea is that if a data.frame is passed in for col_side_colors it should be the same "width" as the matrix being plotted. If a vector is passed in, it's just converted into such a "wide" data.frame. I could try to handle the case of a "narrow" data.frame as well, as long as it is as "long" as the matrix is "wide".

The second error seems to be considerably more mysterious. If I get the ggplot objects (using return_ppxpy (which I edited to return all plot objects) and run ggplotly on the column side plot, it works fine, but not as part of the heatmaply object. It also works if I save heatmap_subplot at the end of heatmaply.heatmapr as a htmlwidget. For some reason, this error seems to be caused by the layout change layout(margin = list(l = margins[2], b = margins[1]))... Which causes only the bottom row of col_side_colors to display a tooltip, and even then only if there is more than one row of colors. Why that is, is somewhat beyond me.

alanocallaghan commented 8 years ago

Okay, found it! The bottom padding seems to be causing it. For some reason, the bottom padding causes the column dendrogram to interfere with the mouse-hover tooltip of the column-side colors, but the column colors don't interfere with the tooltips for the heatmap

alanocallaghan commented 8 years ago

I tried to figure out why this is happening but haven't had any luck yet... I suspect it might be a bug in plotly. For now, I've added a warning about this. I'll add in the dimension checking for col_side_colors I mentioned previously if you think it's advisable

talgalili commented 8 years ago

Hi @Alanocallaghan I am not sure if it should also handle narrow matrix or not, what do you think? Either way, let me know if you think there is any more work you believe should be done at this stage. If yes - I'll wait for your next update. If not, I think I'll push this recent version to CRAN.

Thanks, Tal

alanocallaghan commented 8 years ago

I think it might be dangerous, because in the rare case that a square matrix was being used, it might silently transpose it and give the wrong result.

As for extra work, I've submitted one final pull request that deals with the col_side_colors tooltip issue - I've also raised this issue on the plotly R library repo, so we can hopefully get a more permanent solution eventually Cheers Alan

talgalili commented 8 years ago

Thanks for the push @Alanocallaghan

I just tried your recent pull, but I don't think this is the way to go (sorry): 1) The hover still doesn't seem to work. 2) I fear that letting go of the text at the bottom is too large a price to pay.

I decided to just write a warning saying the hover at the top doesn't work (I pushed it to github now).

alanocallaghan commented 8 years ago

Strange, I've tested it a few times and it has worked for me. Perhaps it's a separate issue in that case. Either way it was definitely not a good solution, I was reluctant to use it

talgalili commented 8 years ago

heatmaply 0.6.0 is on CRAN :) Thank you for all the work @Alanocallaghan