Y-Axis positions of barplot and base plot do not match - r

I was trying to plot a climate diagram and ran into the following problem:
After using barplot(...) for precipitation I superimposed another plot for the temperature. It is necessary for climate diagrams that the two y-axes (mm, °C) align at zero and that the precipitation/temperature ratio is 2:1 (e.g. 20mm precipitation corresponds to 10°C).
The problem: barplot(...) draws the axis to the plot's box while plot(...) leaves some space between the box and the axis margins.
Here is a simplified example. From the grid lines you see that the 0-values do not align:
barplot(0:10)
grid(col=1)
par(new=TRUE)
plot(0:10, xlim=c(-2,14), axes=FALSE)
axis(4,at=c(0:10), labels=c(0:10))
How can I get the right position and scaling of the two axes?

Don't use par(new = TRUE):
barplot(0:10)
grid(col=1)
lines(0:10, type = "p")
axis(4,at = c(0:10), labels = seq(0,20,2))
The function lines() is the right one here. The argument type = p is needed to plot points.
You need to adjust the y-values for the temperature, but now the second y-axis is in the right way, I think.

Related

R: Matching x-axis scales on upper and lower plot using layout with base graphics

I am trying to arrange 3 plots together. All 3 plots have the same y axis scale, but the third plot has a longer x axis than the other two. I would like to arrange the first two plots side by side in the first row and then place the third plot on the second row aligned to the right. Ideally I would like the third plot's x values to align with plot 2 for the full extent of plot 2 and then continue on below plot one. I have seen some other postings about using the layout function to reach this general configuration (Arrange plots in a layout which cannot be achieved by 'par(mfrow ='), but I haven't found anything on fine tuning the plots so that the scales match. Below is a crappy picture that should be able to get the general idea across.
I thought you could do this by using par("plt"), which returns the coordinates of the plot region as a fraction of the total figure region, to programmatically calculate how much horizontal space to allocate to the bottom plot. But even when using this method, manual adjustments are necessary. Here's what I've got for now.
First, set the plot margins to be a bit thinner than the default. Also, las=1 rotates the y-axis labels to be horizontal, and xaxs="i" (default is "r") sets automatic x-axis padding to zero. Instead, we'll set the amount of padding we want when we create the plots.
par(mar=c(3,3,0.5,0.5), las=1, xaxs="i")
Some fake data:
dat1=data.frame(x=seq(-5000,-2500,length=100), y=seq(-0.2,0.6,length=100))
dat2=data.frame(x=seq(-6000,-2500,length=100), y=seq(-0.2,0.6,length=100))
Create a layout matrix:
# Coordinates of plot region as a fraction of the total figure region
# Order c(x1, x2, y1, y2)
pdim = par("plt")
# Constant padding value for left and right ends of x-axis
pad = 0.04*diff(range(dat1$x))
# If total width of the two top plots is 2 units, then the width of the
# bottom right plot is:
p3w = diff(pdim[1:2]) * (diff(range(dat2$x)) + 2*pad)/(diff(range(dat1$x)) + 2*pad) +
2*(1-pdim[2]) + pdim[1]
# Create a layout matrix with 200 "slots"
n=200
# Adjustable parameter for fine tuning to get top and bottom plot lined up
nudge=2
# Number of slots needed for the bottom right plot
l = round(p3w/2 * n) - nudge
# Create layout matrix
layout(matrix(c(rep(1:2, each=0.5*n), rep(4:3,c(n - l, l))), nrow=2, byrow=TRUE))
Now create the graphs: The two calls to abline are just to show us whether the graphs' x-axes line up. If not, we'll change the nudge parameter and run the code again. Once we've got the layout we want, we can run all the code one final time without the calls to abline.
# Plot first two graphs
with(dat1, plot(x,y, xlim=range(dat1$x) + c(-pad,pad)))
with(dat1, plot(x,y, xlim=range(dat1$x) + c(-pad,pad)))
abline(v=-5000, xpd=TRUE, col="red")
# Lower right plot
plot(dat2, xaxt="n", xlim=range(dat2$x) + c(-pad,pad))
abline(v=-5000, xpd=TRUE, col="blue")
axis(1, at=seq(-6000,-2500,500))
Here's what we get with nudge=2. Note the plots are lined up, but this is also affected by the pixel size of the saved plot (for png files), and I adjusted the size to get the upper and lower plots exactly lined up.
I would have thought that casting all the quantities in ratios that are relative to the plot area (by using par("plt")) would have both ensured that the upper and lower plots lined up and that they would stay lined up regardless of the number of pixels in the final image. But I must be missing something about how base graphics work or perhaps I've messed up a calculation (or both). In any case, I hope this helps you get the plot layout you wanted.

Histogram bars exceed chart area in R

I am creating a histogram with the following line:
hist(mydata$freq2,col="lightgreen")
This produces the image below:
I would like the bars to stay within the chart area. Why doesn't R increase the values of the X and Y axis, and how can I increase these values manually?
The bars to stay in the chart area. R calculates the axis dimensions based on your data and with default parameters even extends it a bit.
The axis with its labels is drawn for the boxplot only inside the label range.
If you draw a box around the figure, you will see that the plot uses up the space always the same disregarding of your data. So it is not the bars going outside the chart but the axis being restricted to the labels.
set.seed(12345)
par(mfrow=c(2,2))
plot_random_hist <- function() {
hist(rbeta(100,1,8)*runif(1))
# plot a box to illustrate the plot area
box(col="red")
}
replicate(4, plot_random_hist() )
Have a look at par("usr") to query the dimensions of your plot in user coordinates.
If you need to control the length of the axis and the ticks/labels you can use the axis command and suppress automatic axis in your hist call.
set.seed(12345)
hist(rbeta(100,1,8),yaxt="n")
at <- c(0,10,30,par("usr")[4])
axis(2,at=at,labels=round(at))

setting mfg in a multi plot prevents drawin on margin

I'm trying to add common axes to a bunch of plots by putting them in the outer margin.
Plots are drawn first in a loop (not in the example) then I wanted to draw axes on the bottom of the two rows of plots.
But drawing the axis outside the plotting region is only possible without mfg being changed. How can I enable out-of-plot-drawing after changing mfg?
par(mfrow=c(2,2),
mar=c(1,1,0,0),
oma=c(3,0,0,0))
#Some plots
plot(function(x)x^2,from=-1,to=2, frame.plot=T,axes=F)
plot(function(x)x^3,from=-2,to=2, frame.plot=T,axes=F)
plot(rnorm(10), frame.plot=T,axes=F)
plot(1:10, frame.plot=T,axes=F)
# axis on last drawn plot (mfg=c(2,2)) - works
axis(side=1,line=0,outer=TRUE)
# set mfg to same value (mfg=c(2,2))
par(mfg=c(2,2))
# red axis is clipped to plot region, even with xpd?
axis(side=1,line=-.2,outer=FALSE,xpd=NA,col="red")
par(mfg=c(2,1))
axis(side=1,line=-.2,outer=FALSE,xpd=NA,col="red")
You can set :
par(xpd=NA)
to make sure that the axis is not clipped to the plotting region.

Changing X-axis position in R barplot

I have two values of averages LR50<-(424.8, 425.7). I want to plot these as a barplot barplot(LR50). Now, I don't need any of the information except from ylim=c(424,426.5). When I change the x-axis axis(1,at=c(0,10), pos=424) there is still bar plot that falls below the axis.
How do I get the barplot to only plot from the new x-axis at y=424 and up?
You will need to use the xpd parameter (and set it to FALSE), this will clip the plot to the plotting region.
barplot(LR50,ylim = c(424,426.5),xpd=FALSE)
axis(1,at=c(0,10),pos=424)

Remove spacing around plotting area in r

When I create the following plot I get unwanted space between the plotting area and the axis (i.e. the white space between the blue box and the x axis. How can I remove this space and make the plotting area flush with the plot axes? Thanks.
xleft<-c(1,2,2.5)
xright<-c(2,2.5,2.75)
ybottom<-c(1,2,2.5)
ytop<-c(2,2.5,2.75)
par(mar = c(15,15,2.75,2.75) + 0.1)
plot(c(1,2.75),c(1,2.75),type="n",main="title",xlab="site.x",ylab="ylab")
rect(xleft,ybottom,xright,ytop,col=c("blue","red","green"))
#Label position along axes
x.label.position<-(xleft+xright)/2
y.label.position<-(ybottom+ytop)/2
#Labels
x.label<-c("Long species Name1","Long species Name2","Long species Name3")
y.label<-c("Long species Name4","Long species Name5","Long species Name5")
text(par()$usr[1]-0.5,y.label.position,y.label,xpd=TRUE,adj=1)
text(y=par()$usr[3]-0.5,x=x.label.position,x.label,xpd=TRUE,adj=1,srt=90)
par(xpd=TRUE)
legend(-0.1,0,legend=c("Species A","Species B","Species C"),fill=c("blue", "red", "green"))
UPDATE
I tried the suggestion from plannapus with my actual data but can only get the y-axis to behave is there some else in this chunk of code that is adding space to the sides of the plotting area?
quartz("colour.plot")
par(mar=c(15,15,4,2)+0.1)#sets margins of plotting area
#create the data plot
plot(c(0,100), c(0,100), type = "n", main = paste(x,"vs",y," -",depth),xlab=paste("Species composition in remainder ",x),ylab=paste("Species composition in remainder ",y),asp=1,xaxs="i",yaxs="i")
#Add the rectangles
rect(mdf$xleft,mdf$ybottom,mdf$xright,mdf$ytop,col=mdf$colour)
produces
There is an argument in function plot that handles that: xaxs (and yaxs for the y-axis).
As default it is set to xaxs="r" meaning that 4% of the axis value is left on each side. To set this to 0: xaxs="i". See the xaxs section in ?par for more information.
plot(c(1,2.75),c(1,2.75),type="n",main="title",xlab="site.x",ylab="ylab", xaxs="i", yaxs="i")
rect(xleft,ybottom,xright,ytop,col=c("blue","red","green"))
plot(c(1,2.75),c(1,2.75),type="n",main="title",xlab="site.x",ylab="ylab",axes=F) # ann
axis(1,pos=1)
axis(2,pos=1)
All axes are remove then you can add new axes to the pos you want.

Resources