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.
Related
I would like to plot two graphs in the same plotting region with horizontal grid lines. Each side of the grid lines should give the value for one graph or the other. There should be no y-axis.
The grid() function allows me to simply set the number of bins using the ny= argument. How do I get the corresponding labels to the grid lines? Usually, I would use axis(..., lwd=0) to get the labels. However, the function requires label positions with at=c() and does not feature a ny= argument. Is there a way to automatically set the locations from the number of bins?
Based on Miff's hint below, this should solve the problem.
plot(1:10, axes=FALSE, ylim=c(0,10), ylab="")
par(yaxp=c(0, 10, 5))
axis(2, lwd=0, col.axis="gray")
par(new=TRUE)
plot(60:50, axes=FALSE, ylim=c(50,60), ylab="")
par(yaxp=c(50, 60, 5))
axis(4, lwd=0, col.axis="gray")
grid(NA, NULL)
grid() gets its locations for gridlines from axTicks(), which in turn uses numbers from par("yaxp"). If you modify this parameter (rather than explicitly passing it to grid), the result will then apply to both the grid drawn and the axis. For example:
plot(1:10, axes=FALSE)
axis(2) #Default 4 sections between ticks
par(yaxp=c(par("yaxp")[1:2], 7)) #Lets have seven instead
axis(4)
grid() #Grid now matches with right rather than left
Obviously similar works for the x axis.
Purpose
Create scatter plot with third dimension and multiple colors.
First:
- 3rd dimension with another scale in contrast to y-axis
- create two colors (this is done using col, see code)
Sketch simulating the purpose:
Code
Two "containers" of points plotted in this way:
plot(1:3, c(3,3,3))
points(1:3, c(2,2,2), col="blue")
Another nice plotting is done by:
#install.packages("hexbin")
library(hexbin)
x <- 1:1000#rnorm(1000)
y <- 1500:501#rnorm(1000)
bin<-hexbin(x, y, xbins=50)
plot(bin, main="Hexagonal Binning")
But I do not know how to use hexbin (I do not understand the functionality). There are needed two colors which I do not know how to generate.
Questions
How to create the 3rd axis with other scaling than the y-axis?
Can I use ´hexbin´ to get the result?
For some reason, using points() does not work, but using plot() does work:
#Set margin on right side to be a bit larger
par(mar = c(5,4.5,4,5))
#Plot first set of data
plot(1:3, rep(3,3), ylim=c(-5,5), xlab="X-Axis", ylab="Y-Axis 1")
#Plot second set of data on different axis.
par(new=T)
plot(1:3, rep(5,3), ylim=c(-10,10), col="blue", xlab="", ylab="", axes=FALSE)
#Add numbers and labels to the second y-axis
mtext("Y-Axis 2",side=4,line=3)
axis(4, ylim=c(-10,10))
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 :)
I have a series of plots that I want on a single page. I first use the command layout to specify my plot layout:
layout(matrix(c(1,1,2,2,1,1,2,2,3,4,5,6),3,4,byrow=TRUE))
For plot 1, I have something like:
plot(Easting,Northing, pch=16, col=grey(cex.size)) #The cex.size colours my dots according to some value
I now want to draw an inset plot on plot 1, but not move to plot 2 yet.
I tried following the code :
par(fig=c(0.75, 1, 0, 0.25), new = T)
plot(spp.tmp[,1:2], col=cols[spp.tmp[,3]+1], pch=16)
par(fig=c(0,1,0,1))
But this doesnt work, as par(fig()) command overwrites my layout, and the inset plot appears on the bottom corner of my overall figure, not just in the bottom corner of plot 1.
Two options,
You coul try and include the inset within your layout command (if you were to stick with layout
Here is a case where the first plot spans two rows and column, the second is an inset in the bottom right corner of the first. The third plot is below, the same size as the first, but without an inset.
layout( matrix(c(1,1,1,2,3,3,3,3), 4, 2, byrow = TRUE) )
## show the regions that have been allocated to each plot
layout.show(3)
An alternative is to use subplot from the TeachingDemos package
library(TeachingDemos)
layout(matrix(c(1,1,0,2),2,2,TRUE))
plot(1)
subplot(plot(1), x = c(1.2),y=0.8)
plot(2)
This is my hatchet approach using base graphics. Because your messing around with par(), why dont you change around the order in matrix and plot the tricky one last. This way the par settings do not affect any more plots in your layout, if you were to plot the tricky one first. It seems simplistic in this example, but when you have lots of plots and you want an inset in only 1, it works.
##generate some data
x<-rnorm(50)
y<-rnorm(50)
##set the layout
##so your first plot is plotted last
layout(matrix(c(2,2,0,1), 2,2, byrow=T))
#plot 1 is on the bottom right
plot(x,y, col="grey30", xlab="", ylab="")
#plot 2 is across the top
plot(x,y, col="grey30", xlab="", ylab="")
##set par to place the next plot in the existing plotting area
## and use fig to position it
par(fig=c(.65, .95, .55, .85), new = TRUE)
#inset 3rd plot int top plot, this effectively gives you a blank plot to populate
plot(x,y, col="white", xlab="", ylab="")
#and make the background white
rect(par("usr")[1],par("usr")[3],par("usr")[2],par("usr")[4],col = "white")
##then just add your points afterwards
points(x,y,col="tomato")
I am running the following code:
par(bg="yellow", mar=c(2,2,2,2))
layout(matrix(c(rep(1,12),2:13),nrow=2,byrow=T),width=myWidth)
plot(days,sum_precip,type="l",xaxt="n",yaxt="n",ann=FALSE,
xlab="TEST",main="WEWQWE",ylab="dsads")
On the last statement, my plot fails to display any labels even after specifying this in arguments. Is it because my margins are too small?
I am trying to add a header for the x-axis for each of my graphs on the bottom row of the layout.
Example of Issue:
Note, I'm more curious about why this does not work. I know I can just specify an axis(..), but this is more out of interest.
Here a solution using mtext. see ?mtext
Text is written in one of the four margins of the current figure
region or one of the outer margins of the device region.
par(bg="lightyellow", mar=c(2,2,2,2))
layout(matrix(c(rep(1,12),2:13),nrow=2,byrow=T))
replicate(13,
{ plot(x=1:5,y=cumsum(1:5),type="l",xaxt="n",yaxt="n",ann=FALSE)
mtext(text='TEST',side=1,line=1)
mtext(text='dsads',side=2,line=1)
})
EDIT
You can set the margin for every plot.
par(bg="lightyellow", mar=c(2,2,2,0))
layout(matrix(c(rep(1,12),2:13),nrow=2,byrow=T))
for(i in 1:13){
if (i %in% 1:2){
plot(x=1:5,y=cumsum(1:5),type="l",xaxt="n",yaxt="n",ann=FALSE)
mtext(text='TEST',side=1,line=1)
mtext(text='dsads',side=2,line=1)
}else{
par( mar=c(2,0,2,0))
plot(x=1:5,y=cumsum(1:5),type="l",xaxt="n",yaxt="n",ann=FALSE)
}
}
Yeah margins are too small.
Example:
par(mar=rep(4,4))
plot(1, 1, xaxt='n', xlab='x', yaxt='n', ylab='y')
this shows the labels (sorry it's tiny).
However using par(mar=rep(2,4)):
The labels are cut off.
You can use the mgp argument to modify the offset (in lines) of the axis text from the axis. In particular (?par), mgp is a vector of length 3 where mgp[1] is the lines between the plot and axis label, mgp[2] is for the axis line itself and mpg[3] is for the axis tick labels.
So:
par(mar=rep(2,4))
# mgp[2:3] irrelevant in this case as we have turned
# axis line/ticks off; doesn't matter what they are set to
plot(1, 1, xaxt='n', xlab='x', yaxt='n', ylab='y', mgp=c(1,0,0))
This will place the axis labels 1 line away from the axis (i.e. on the second line away) which just fits into our margin of 2,2,2,2.