I want to plot a centered legend outside of the plotting area in a device having multiple plots. There has been many questions (with slight variations) asked in SO about changing the position of legend in a R plot.
For example:
1) R - Common title and legend for combined plots
2) Common legend for multiple plots in R
3) Plot a legend outside of the plotting area in base graphics?
etc.
Now what I understood from the above questions is that I got to set the option xpd = T or xpd = NAto plot legends at the outer margins. However when I try this, it somehow does not work for me ..
par(mfrow=c(1,2),oma=c(0,3,0,0),xpd=TRUE)
plot(c(5,10),col=c("red","blue"),pch=20,cex=2,bty="n",xlab="",ylab="")
barplot(c(5,10),col=c("red","blue"))
mtext(text="My two plots",side=3,cex=2,outer=TRUE,line=-3)
legend("top",legend=c("A", "B"),fill=c("red","blue"),ncol=2,xpd=NA,bty="n") # Option 1
legend(x=0.01,y=11,legend=c("A", "B"),fill=c("red","blue"),ncol=2,xpd=TRUE,bty="n") # Option 2
Now my question is, how does xpd exactly work ? as I am unable to figure out why shouldn't the legend not be placed outside the plot area with xpd=T.
I apologize in advance if some consider this as a duplicate of the above questions !!
Help is much appreciated
Ashwin
Option #1 is likely the route you should take, with xpd=NA. It does not automatically place the legend in the outer margins, but it allows you to place the legend anywhere you want. So, for example, you could use this code to place the legend at the top of the page, approximately centered.
legend(x=-1.6, y=11.6, legend=c("A", "B"), fill=c("red", "blue"), ncol=2, xpd=NA, bty="n")
I chose these x and y values by trial and error. But, you could define a function that overlays a single (invisible) plot on top of the ones you created. Then you can use legend("top", ...). For example
reset <- function() {
par(mfrow=c(1, 1), oma=rep(0, 4), mar=rep(0, 4), new=TRUE)
plot(0:1, 0:1, type="n", xlab="", ylab="", axes=FALSE)
}
reset()
legend("top", legend=c("A", "B"), fill=c("red", "blue"), ncol=2, bty="n")
I also had a hard time to get coordinates on the margins. I think I found a solution, you can specify coordinates for the legend using:
getCoords() function.
Look also to legend_margin function from plotfunctions package.
So combining the solution from Jean V. Adams with one of these functions should get you there.
Hope that works :)
Related
If you call function hist on r, you will note that the box that usually surrounds plotting region doesn't appear, instead, only rulers indicating plot scale appear on the bottom and on the left. If you use r a lot you may probably have noticed this already. my question is: there is some graphical parameter or workaround to make this happen on any other plot of basic r (like in a scatterplot, a line plot, a qq plot or whatever)?
The only parameter I found was axes, but setting it to FALSE makes it disappear not only the box, but also the rulers.
You are looking for box().
op <- par(mfrow=c(1, 2))
hist(mtcars$mpg, sub="w/o box")
hist(mtcars$mpg, sub="w/ box")
box() ## <-- this
par(op)
the answer is bty graphical parameter:
x= matrix(rnorm(100), ncol= 2)
plot(x, bty= 'n')
I am wanting to get the cleanest look using this code chunk which overlays my plot in R
legend(130, 0.0150, legend = c(paste0("Large diameter ", format(center, digits=6)),
paste0("Minimum ", format(min2, digits=6))),
bty = "n")
Notice the large white spaces. But this achieves the effect I want
But I know there's a better way to do this! I additionally want to add more descriptive statistics to the plot and this has to be a very inefficient way of doing it. So, what's the best way to align the text and numbers? Any way to beautify to this further? Thanks all!
You could just print two legends side by side.
Example
Example plot:
curve(cos(x)/100, xlim=c(0, 250), ylim=c(0, .02), col="blue")
center <- 135.873; min2 <- 86.3301 # values
Legend:
legend(130, 0.0150, legend=c("Large diameter", "Minimum"), bty="n")
legend(200, 0.0150, legend=c(format(center, digits=6),
format(min2, digits=6)), bty="n")
As indicated in the title above, I want to change the column labels in the heatmap figure produced by heatmap.2 from package gplots in R to symbols rather than text. May I know if it is possible, and if so, how to do it?
This is a sample code to generate heatmap using heatmap.2:
library(gplots)
data<-sample(1:100,size=80)
M<-matrix(data,nrow=10,ncol=8)
colnames(M)<-c("W1_1","W1_2","W1_3","W1_4","B1_1","B1_2","B1_3","B1_4")
heatmap.2(M, trace="none", dendrogram="none")
This is the heatmap result:
In this case, the column labels are "W1_1","W1_2","W1_3","W1_4","B1_1","B1_2","B1_3","B1_4". May I know If it is possible to use two symbols to represent W1 and B1 group respectively and show in the final figure.
I have attached a sample below (changed via photoshop):
Thanks in advance for all the helps!
Here's another possibility with standard image function:
op <- par(mar=c(4,2,2,4))
image(seq(nrow(M)), seq(ncol(M)), M, axes=F, xlab="", ylab="")
axis(side=4, at=seq(ncol(M)))
par(xpd=TRUE)
points(seq(nrow(M)), rep(0, nrow(M)),
pch=c(16, 15), col=c("cyan", "pink"), cex=2
)
par(op)
I am trying to add a simple legend to a customized pairs graph.
Here is the reproductible code (without my customized pairs function) :
layout(cbind(1,2),width=c(1,1))
layout.show(2)
pairs(USJudgeRatings)
Why is the pairs function "erasing" my layout information ?
A warning contained in the help for layout is
These functions are totally incompatible with the other mechanisms for arranging plots on a device: par(mfrow), par(mfcol)
Unfortunately, pairs uses mfrow for arranging the plots.
Using the hints from Duncan Murdoch and Uwe Ligges on R help, you can set oma to a reasonable value to give you room for a legend on the side, eg
pairs(iris[1:4], main = "Anderson's Iris Data -- 3 species",
pch = 21, bg = c("red", "green3", "blue")[iris$Species],
oma=c(4,4,6,12))
# allow plotting of the legend outside the figure region
# (ie within the space left by making the margins big)
par(xpd=TRUE)
legend(0.85, 0.7, as.vector(unique(iris$Species)),
fill=c("red", "green3", "blue"))
I have all the parameters fixed to describe one plot including oma, mar, mgp, ... I want to divide the very plot area into several separate, exactly equally sized smaller plot areas which share both x and y label. For example something like this:
I found solutions to combine plots but with seperate axes. Any starting point for the problem here?
You can set the outer margins to be big enough to hold the axes and labels, then set the regular margins to 0. Use par(mfrow or layout to split the inner region into the panels that you want, then do the plots without the axes and labels and add the axes and labels into the outer margins:
par( oma=c(5,4,4,1)+0.1, mar=c(0,0,0,0) )
layout( matrix( 1:3, nrow=1 ) )
for( i in levels(iris$Species) ) {
with( iris[ iris$Species==i, ], {
plot(Sepal.Width, Sepal.Length, ann=FALSE, xaxt='n', yaxt='n',
ylim=range(iris$Sepal.Length))
axis(1, outer=TRUE)
mtext(side=3, i ) }
)
}
axis(2, outer=TRUE)
But it is probably simpler using lattice or ggplot2.
I'd suggest looking at using ggplot2 to see if there is a solution there that meets your needs. I find the plot you linked to be visually confusing.