Change the layout of heatmap.2 figure - r

We are using heatmap.2 to draw figures. With the default parameters we can get the following layout/outlook (see Figure 1).
How to remove the right row names/row labels, for we have thousands of labels (see Figure 1) ?
Can we draw the Color Key upwards to downwards (see Figure 2) ?
Figure 1
Figure 2

Question 1: The row names can be removed by setting labRow = "".
Question 2: This is not possible without changing the function. heatmap.2 uses a 2 by 2 table for the layout and puts the key in the upper left cell if one is to be added. You would need to edit the function to have a 2 by 3 layout and put the key in the lower right cell, editing the display to show as indicated.

Question 2. Ian gives an excellent explanation for the layout of the heatmap.2 components. You can change the layout (number of cells in a table where each element is "plotted", e.g. 2x2, 2x3, 3x2, 3x3) and the position of each of the elements of the heatmap (i.e. heatmap, row dendrogram, column dendrogram, and key).
For example:
# Define custom layout for heatmap
mylmat = rbind(c(0,3,0),c(2,1,0),c(0,4,0)) # creates 3x3 table with location of heatmap elements defined
mylwid = c(1.5,4,0.5)
mylhei = c(1.5,4,1)
# Plot your heatmap
heatmap.2(matrix.name, lmat=mylmat, lwid=mylwid, lhei=mylhei, ...)
Although you cannot change the key to be vertical versus horizontal (as far as I know!), you can position it anywhere around the heatmap and/or dendrograms.

Related

Remove empty space from matplot

When using matplot() there always is a lot of empty space on the panel.
Normaly I cut it out with an external program, but it becomes a problem when arranging multiple graphs in one panel.
The option plot(x,y,...,,xaxs="i",yaxs="i") removes space around the x-axis (plot becomes wider), but not for the y-axis. I have also tried to readjust the layout matrix, giving more or less rows in the matrix to plots.
I first arrange my plots with layout() (works the same for par(mfrow=c(#,#))). Then I add the plots.
layout(rbind(
c(1,1,2,2),
c(1,1,2,2),
c(3,3,4,4),
c(3,3,4,4),
c(5,6,7,8),
c(9,10,11,12)
))
matplot(matrix(runif(100),nrow=10),type='l',xaxs="i",yaxs="i") # plot 1 upper left
matplot(matrix(runif(100),nrow=10),type='l',xaxs="i",yaxs="i") # plot 2 upper right
# fill the other panels
for(i in 3:12){
plot(1:10,runif(10),type='p',xaxs="i",yaxs="i")
}
When plotting this, a lot of the panel is wasted with empty space, while the plots are cropped. I want panel space to be filled with (nice) plots, making them as large as possible.
?par, entry mar is your friend.
with par(mar=c(bottom,left,top,right)) you can set the margins around your plot to move them closer to each other

R: setting label spacing and position on a bar plot

I want to present percentages over a 24h period in 15 min intervals as a bar plot.
When I use barplot(), the labels for those timepoints are more or less randomly chosen by R (depending on how I format the window. I know it's not random, but it's not what I want either). I would rather have them evenly spaced at 1 h intervals (that is every 4th bar).
I have searched extensively on this and know i can add labels later with axis() but I have not found a way to set which bars are labeled and which are left blank.
So here is an example. Sorry for the long lines:
x<-sample(1:100,96)
Labels<-c("09","09:15","09:30","09:45","10:00","10:15","10:30","10:45","11","11:15","11:30","11:45","12","12:15","12:30","12:45","13","13:15","13:30","13:45","14","14:15","14:30","14:45","15","15:15","15:30","15:45","16","16:15","16:30","16:45","17","17:15","17:30","17:45","18","18:15","18:30","18:45","19","19:15","19:30","19:45","20","20:15","20:30","20:45","21","21:15","21:30","21:45","22","22:15","22:30","22:45","23","23:15","23:30","23:45","00","00:15","00:30","00:45","01","01:15","01:30","01:45","02","02:15","02:30","02:45","03","03:15","03:30","03:45","04","04:15","04:30","04:45","05","05:15","05:30","05:45","06","06:15","06:30","06:45","07","07:15","07:30","07:45","08","08:15","08:30","08:45")
names(x)<-Labels
barplot(x)
I do not think you can force R to show every label if it does not have enough space. But at least if you want to add the labels every 1h, the following code should work :
x<-sample(1:100,96)
Labels<-c("09","09:15","09:30","09:45","10","10:15","10:30","10:45","11","11:15","11:30","11:45","12","12:15","12:30","12:45","13","13:15","13:30","13:45","14","14:15","14:30","14:45","15","15:15","15:30","15:45","16","16:15","16:30","16:45","17","17:15","17:30","17:45","18","18:15","18:30","18:45","19","19:15","19:30","19:45","20","20:15","20:30","20:45","21","21:15","21:30","21:45","22","22:15","22:30","22:45","23","23:15","23:30","23:45","00","00:15","00:30","00:45","01","01:15","01:30","01:45","02","02:15","02:30","02:45","03","03:15","03:30","03:45","04","04:15","04:30","04:45","05","05:15","05:30","05:45","06","06:15","06:30","06:45","07","07:15","07:30","07:45","08","08:15","08:30","08:45")
b=barplot(x,axes = F)
axis(2)
axis(1,at=c(b[seq(1,length(Labels),4)],b[length(b)]+diff(b)[1]),labels = c(Labels[seq(1,length(Labels),4)],"09"))

Using R legend (graphics package), fill legend left to right instead of top to bottom

I'm trying to plot a legend at the bottom of a main plot area comprised of multiple small plots (4 rows x 5 columns). I figured out how to center the legend at the bottom with the aid of this answer. I'm interested in having a horizontal legend, so I tried to use legend(x="center",lbls, horiz=TRUE), which would have served my purposes - except that my labels are too long and it goes off the plot area. I decided that a 2 row x 4 column layout will work best (I have 8 labels).
However, legend(x="center",lbls, ncol = 4) fills in the columns first (i.e. top to bottom), and I'd like to fill in by row first (i.e. left to right). Is there a workaround for this that doesn't involve using multiple legends?

How to superimpose a histogram on each panel

I would like to superimpose, on each lattice histogram panel, an additional histogram (which will be the same in each panel). I want the overlayed histogram to have solid borders but empty fill (col), to allow comparison with the underlying histograms.
That is, the end result will be a series of panels, each with a different colored histogram, and each with the same extra outline histogram on top of the colored histogram.
Here's something that I tried, but it just produces empty panels:
foo.df <- data.frame(x=rnorm(40), categ=c(rep("A", 20), rep("B", 20)))
bar.df <- data.frame(x=rnorm(20))
histogram(~ x | categ, data=foo.df,
panel=function(...){histogram(...);
histogram(~ x, data=bar.df, col=NULL)})
(My guess is that I need to use panel.superpose, but this function is somewhat confusing. Sarkar's book doesn't explain how to use it, and the R help page has no examples. I'm finding it difficult to make sense of the panel.superpose help page without already having a basic understanding. There are a very small number of examples that I've found on the web, but I have been unable to figure out what aspects of those examples apply to my case. This answer is surely relevant, but I don't understand its use of panel.groups, and the example overlays three different groups from a single dataframe, whereas I want to repeatedly overlay the same data on multiple panels that also have different data .)
I continued working on this problem, and came up with an answer. I had been on the right track but got several crucial details wrong. Comments in the code below spell out important points.
# Main data, which will be displayed as solid histograms, different in each panel:
foo.df <- data.frame(y=rnorm(40), cat=c(rep("A", 20), rep("B", 20)))
# Comparison data: This will be displayed as an outline histogram in each panel:
bar.df <- data.frame(y=rnorm(30)-2)
# Define some vectors that we'll use in the histogram call.
# These have to be adjusted for the data by trial and error.
# Usually, panel.histogram will figure out reasonable default values for these.
# However, the two calls to panel.histogram below may figure out different values,
# producing pairs of histograms that aren't comparable.
bks <- seq(-5,3,0.5) # breaks that define the bar bins
yl <- c(0,50) # height of plot
# The key is to coordinate breaks in the two panel.histogram calls below.
# The first one inherits the breaks from the top-level call through '...' .
# Using "..." in the second call generates an error, so I specify parameters explicitly.
# It's not necessary to specify type="percent" at the top level, since that's the default,
# but it is necessary to specify it in the second panel.histogram call.
histogram(~ y | cat, data=foo.df, ylim=yl, breaks=bks, type="percent", border="cyan",
panel=function(...){panel.histogram(...)
panel.histogram(x=bar.df$y, col="transparent",
type="percent", breaks=bks)})
# col="transparent" is what makes the second set of bars into outlines.
# In the first set of bars, I set the border color to be the same as the value of col
# (cyan by default) rather than using border="transparent" because otherwise a filled
# bar with the same number of points as an outline bar will be slightly smaller.

R How to build angled column headings above columns in heatmap.2: pass (text) plot to the layout?

I am very close to the heatmap I want, but I have been struggling for several days to figure out the headings problem. I want angled headings (such as 45 or 50 degrees) at the top of each column. I have already suppressed the dendrograms (for both columns and rows), and used the first column of my matrix (depth) as labels for the rows.
From my many, many searches on this issue, I see that mtext won't help me because the text cannot be rotated in mtext. Then I thought I could do it with text, but the column labels get overwritten onto the heatmap itself; they "disappear" (get covered) when the words reach the edge of the heatmap layout space. So I examined the layout used by heatmap (thanks very much to #Ian Sudbery), and it occurred to me that what I really need is a dedicated space in the layout for my column headings. I can allocate that space using the layout function, and I have done so in the code below. But I think the next step may involve getting inside the heatmap.2 code. Heatmap.2 calls four plots (two of which I have suppressed, the dendrograms). How do I make it call a fifth plot? And if that is possible, how do I tell it that I want to use text as my fifth "plot", where the text is my column headings, rotated 50deg?
Thanks very much for any ideas. Please forgive the clumsy way I've provided sample data in the code below; I am new to R and generally do not know the most elegant way to do most things.
par(oma=c(0.5,0.5,.5,0.5)) # outer margins of whole figure
lmat = rbind(c(3,5,5),c(2,1,1),c(0,4,0))
lwid = c(.08,.9, .1)
lhei = c(1,4,1.5)
Depth<-c("0m","20m","40m","60m","80m","100m")
Sept2008<-c(3,6,8,10,15,16)
March2010<-c(10,12,11,13,12,11)
Sept2010<-c(5,6,NA,8,11,13)
March2011<-c(4,6,10,NA,14,14)
Sept2011<-c(2,5,3,9,16,12)
heatmap_frame=data.frame(Depth=Depth,Sept2008=Sept2008,March2010=March2010,Sept2010=Sept2010, March2011=March2011, Sept2011=Sept2011)
row.names(heatmap_frame)<-heatmap_frame$Depth
heatmap_frame<-heatmap_frame[,-1]
heatmap_matrix <- as.matrix(heatmap_frame)
labCol=c("Sept 2008","March 2010","Sept 2010","March 2011","Sept 2011")
cexCol=1.1
heatmap <- heatmap.2(heatmap_matrix, dendrogram="none", trace="none",Rowv=NA, Colv=NA,
col = brewer.pal(9,"Blues"), scale="none", margins=c(2,5),labCol="",
lmat=lmat, lwid=lwid,lhei=lhei, density.info="none",key=TRUE)
# want to plot a fifth area, to use for col labels
# don't know how to pass a text line to the heatmap.2/layout/matrix to print as my fifth plot
mtext("Use for main title", side=3,outer=F,line=2.75, font=2, cex=1.25)
# testing the text function; did not work as desired
#text(x=1, y=1, labels="Label_1",xpd=T)
text(x=c(0,.2,.4,.6,.8), y=0.95, pos=3, srt=50, labels=labCol,xpd=T, cex=1)
Here's a hack that doesn't involve pulling apart the convoluted code of heatmap.2:
pos2 <- locator() #will return plotting coordinates after doing this:
# Shift focus to the graphics window by clicking on an edge
# Left-Click once where you want the first label to be centered
# Left-click again on the point where you want the last label centered
# Right-Click, then return focus to the console session window
pos2 <- structure(list(x = c(0.27149971320082, 0.858971646016485),
y = c(0.861365598392473, 0.857450478257082)),
.Names = c("x", "y"))
text(x=seq(pos2$x[1], pos2$x[2], len=5), y=rep(pos2$y[1],5) ,
srt=50, xpd=TRUE, adj = 0,
labels=c("Sept 2008","March 2010","Sept 2010",
"March 2011","Sept 2011") )
I don't know if you actually need the xpd in there, since it appears that after heatmap.2 is finished it returns the window to its native coordinates: [0,1]x[0,1]

Resources