Question

I use heatmap.2 from gplots to make a heatmap:

library(gplots)
# some fake data
m = matrix(c(0,1,2,3), nrow=2, ncol=2)
# make heatmap
hm = heatmap.2(m)

When I do 'heatmap.2' directly I get a plot that I can output to a device. How can I make the plot again from my variable 'hm'? Obviously this is a toy example, in real life I have a function that generates and returns a heatmap which I would like to plot later.

Was it helpful?

Solution 2

There are several alternatives, although none of them are particularly elegant. It depends on if the variables used by your function are available in the plotting environment. heatmap.2 doesn't return a proper "heatmap" object, although it contains the necessary information for plotting the graphics again. See str(hm) to inspect the object.

If the variables are available in your environment, you could just re-evaluate the original plotting call:

library(gplots)
# some fake data (adjusted a bit)
set.seed(1)
m = matrix(rnorm(100), nrow=10, ncol=10)
# make heatmap
hm = heatmap.2(m, col=rainbow(4))

# Below fails if all variables are not available in the global environment
eval(hm$call)

I assume this won't be the case though, as you mentioned that you are calling the plot command from inside a function and I think you're not using any global variables. You could just re-construct the heatmap drawing call from the fields available in your hm-object. The problem is that the original matrix is not available, but instead we have a re-organized $carpet-field. It requires some tinkering to obtain the original matrix, as the projection has been:

# hm2$carpet = t(m[hm2$rowInd, hm2$colInd])

At least in the case when the data matrix has not been scaled, the below should work. Add extra parameters according to your specific plotting call.

func <- function(mat){
    h <- heatmap.2(mat, col=rainbow(4))
    h
}

# eval(hm2$call) does not work, 'mat' is not available
hm2 <- func(m)

# here hm2$carpet = t(m[hm2$rowInd, hm2$colInd])
# Finding the projection back can be a bit cumbersome:
revRowInd <- match(c(1:length(hm2$rowInd)), hm2$rowInd)
revColInd <- match(c(1:length(hm2$colInd)), hm2$colInd)
heatmap.2(t(hm2$carpet)[revRowInd, revColInd], Rowv=hm2$rowDendrogram, Colv=hm2$colDendrogram, col=hm2$col)

Furthermore, I think you may be able to work your way to evaluating hm$call in the function's environment. Perhaps with-function would be useful.

You could also make mat available by attaching it to the global environment, but I think this is considered bad practice, as too eager use of attach can result in problems. Notice that in my example every call to func creates the original plot.

OTHER TIPS

I would do some functional programming:

create_heatmap <- function(...) {
    plot_heatmap <- function() heatmap.2(...)
}

data = matrix(rnorm(100), nrow = 10)

show_heatmap <- create_heatmap(x = data)

show_heatmap()

Pass all of the arguments you need to send to plot_heatmap through the .... The outer function call sets up an environment in which the inner function looks first for its arguments. The inner function is returned as an object and is now completely portable. This should produce the exact same plot each time!

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top