Y axis out of plotting region with barplot() in R - r

I'm having problems getting the y axis on a horizontal barplot() within the plotting region. See this example, I thought that using ylim and/or yaxp would stop this going off the plotting region, but it doesn't seem to work.
I've tried to reproduce the set up I've got:
x <- matrix(abs(rnorm(34)), nrow = 34, ncol = 3)
rownames(x) <- c(seq(0,6600,200))
barplot(x[,3], horiz=TRUE, space = 0.4, main = "Title", las=1, cex.names=0.8, ylab="y label")
But the axis goes of the plotting region if I add ylim:
barplot(x[,3], horiz=TRUE, space = 0.4, ylim = c(0,25), yaxp=c(0,25,1), main = "Title", las=1, cex.names=0.8, ylab="y label")

For some (strange?) reason, barplot has xpd = TRUE by default, setting this to false will cause it to clip like most plot functions:
barplot(x[,3], horiz=TRUE, space = 0.4, ylim = c(0,25), yaxp=c(0,25,1),
main = "Title", las = 1, cex.names = 0.8, ylab = "y label", xpd = FALSE)

The key here is to forget about ylim when using barplot and instead just send the desired plotting range in the data:
barplot(x[1:25,3], horiz=TRUE, space = 0.4, yaxp=c(0,25,1), main = "Title", las=1,
cex.names=0.8, ylab="y label")
Also note that indexing in R starts at 1 and not at 0 as it might in some other languages.

Related

How to shift bars from y-axis using barplot() R

I have a barplot with the following code:
bp <- barplot(COL0.matrix,
beside=T,
col=col,
ylim=c(0,100), yaxt="n",
xlab="Time",ylab="Relative Electrolyte Leakage (%)",
las=1,xaxt = "n",
cex.axis=1.5, cex.names= 1.5, font=2, font.lab=2, cex.lab=1.5, family="A", space=c(0,0,1,0), xaxs = 'i')
axis(side=2, family="A", cex.axis=0.8, las=1, font=2, pos=0, tck=c(0), at=c(0,10,20,30,40,50,60,70,80,90,100), labels=c("0", "10","20","30","40","50","60","70","80","90","100"))
axis(side=2, at=c(0,10,20,30,40,50,60,70,80,90,100), labels = c(NA),tcl=c(-0.25),pos=0)
axis(side=2, at=c(0,10,20,30,40,50,60,70,80,90,100), labels = c(NA),tcl=c(0.25),pos=0)
axis(side=1, at=c(1.2, 4.2), labels = c("Dawn", "Dusk"),tck=c(0), family="A", cex.axis=1.5, font=2, pos=0)
This results in the following barplot:
I am trying to shift the bars which are right next to the y-axis away. I have tried changing space=(...) but this shifts the whole x-axis so that the x and y axis no longer join.
Is there a way of shifting the left two bars over?
You can use the line parameter to move the axis over instead of moving the bars. You want to remove the pos = 0 and define the y title outside the barplot function so you can also control its position. Also you will want to play with the par(mar = ... part so it looks right for your device. For if you save in a pdf device your margin and even the cex parameters probably will need adjusting to make it nice. Also I set the graphics parameter xpd = TRUE to allow the lines function in the last line to plot into the margin space. If you don't do that you'll have a x axis that doesn't meet the y axis. If you don't want that then remove the last line.
COL0.matrix <- structure(c(71.44109964, 78.43178612, 64.31581642, 70.3339388 ), .Dim = c(2L, 2L), .Dimnames = list(c("Control", "bold(\"Col-0 840g ha\"^\"-1\")" ), c("Dawn", "Dusk")))
col = c("white", "grey70", "white", "grey70")
par(mar = c(5,7,5,5), xpd = TRUE)
bp <- barplot(COL0.matrix,
beside=T,
col=col,
ylim=c(0,100), yaxt="n",
xlab="Time", ylab = "",
las=1,xaxt = "n",
cex.axis=1.5,
cex.names= 1.5,
font=2,
font.lab=2,
cex.lab=1.5,
family="A",
space=c(0,0,1,0),
xaxs = 'i')
mtext("Relative Electrolyte Leakage (%)", side = 2, font = 2, cex = 1.5, line = 4)
axis(side=2, family="A", cex.axis=0.8,
las=1, font=2, tck=c(0),
at=c(0,10,20,30,40,50,60,70,80,90,100),
labels=c("0", "10","20","30","40","50","60","70","80","90","100"),
line = 1)
axis(side=2, at=c(0,10,20,30,40,50,60,70,80,90,100), labels = c(NA),tcl=c(-0.25), line = 1)
axis(side=2, at=c(0,10,20,30,40,50,60,70,80,90,100), labels = c(NA),tcl=c(0.25), line = 1)
axis(side=1, at=c(1.2, 4.2), labels = c("Dawn", "Dusk"),tck=c(0), family="A", cex.axis=1.5, font=2, line = 0)
lines(x = c(-0.3, 5.3), y = c(0, 0))

Plots side by side in R. Controling size accurately

I need to put 2 columns of plots side by side (only one row in the example) and I can't manage to control the size of the plots and the position of the labels so that both plots are exactly aligned. This is the code the have now:
split.screen(c(1,2))
screen(1)
par(oma=c(0,1,0,0), mai=c(0.6,0.36,0.5,0.7), cex=0.5, mgp = c(0.5,0.1, 0), tck = -0.05)
plot(datos$UN.CJF*1000, datos$Methane.Produced.CJF, pch = 16, cex = 0.5, col ="black",
xlab = "UN (g/d)", ylab = expression('CH'[4]*'(g/d)'))
title(main = "a)", cex=0.8, line=0.5, adj=0, cex.lab=1.2)
datos$LWchangeD.CJF <- datos$LWchange.CJF/15
screen(2)
par(oma=c(0,1,0,0), mai=c(0.6,0.36,0.5,0.7), cex=0.5, mgp = c(0.5,0.1, 0), tck = -0.05)
scatter2D(datos$UN.CJF*1000, datos$Methane.Produced.CJF,
pch = 16,
xlab = "UN (g/d)", ylab = "",
colvar = datos$LWchangeD.CJF, clab = c("Liveweight change (kg/d)")
)
title(main = "b)", cex=0.8, line=-0.7, adj=0, cex.lab=1.2)
Notice how the size of the 2 figs is different
There must be a better way to do it.
Any help would be MUCH appreciated
Alvaro
grid.arrange did the trick, but I first re-did all my plots in ggplot2.
Thanks a lot for your suggestions
Alvaro

Why the y axis in my barplot doesn't show completely?

I don't know how to change the code so that the y-axis in the barPlot shows completely? I expect it to show up to 10 as I have a 9.2 in my data points but it shows only up to 8. Any idea what's the hack to this?
Here's the code:
And here's what it shows:
just set the ylim = c(0, 10) like the way you changed the xlim
Whatever the axis that the groups go on isn't drawn by default, so a vertical bar plot won't have x-axis; horizontal won't have y-axis. You can add that of course. Use the return value of barplot:
par(mfrow = c(2, 1))
bp <- barplot(c(8, 5), width = .5, main = 'Feature Exploration', xlim = c(0,4), ylim = c(0, 10),
ylab = 'Errors (%)', xlab = 'ML Models', col = c('gray27','orangered4'))
## this will draw the x-axis but at points 1, 2, 3, ... which is not
## where the centers of your bars are plotted; you get that info in bp
axis(1)
bp <- barplot(c(8, 5), width = .5, main = 'Feature Exploration', xlim = c(0,4), ylim = c(0, 10),
ylab = 'Errors (%)', xlab = 'ML Models', col = c('gray27','orangered4'))
## so try again with a fancy axis, bp is a matrix containing the centers
## of the plotted bars
axis(1, at = bp, labels = c('Model1','Model2'), lwd = 0, lwd.ticks = 1, tcl = -.5)

How to draw single axis plot in R

I wish to draw very very simple line with three numbers. It would be like below
|------|--------------|
0.5 1.5 3.4
Is it too simple to ask?
First, plot nothing, remove the axes, and add an x-axis back in at the specified points:
x <- c(.5, 1.5, 3.4)
plot(0, xlim = c(0, 3.5), axes=FALSE, type = "n", xlab = "", ylab = "")
axis(1, at = x, labels = x)
plot(1:10, rep(0,10), type='b', pch='|', axes=F, xlab="", ylab="", xlim=c(0,10))
text(1:10, rep(-0.1,10), labels=1:10)
margins and plot size can be tweaked with X11 and par
You can do it in grid,
library(grid)
grid.newpage()
grid.xaxis(at=c(0.5, 1.5, 3.4),
vp=vpStack(viewport(height=unit(2,"lines")),
viewport(y=1, xscale = c(0.4, 3.5), just="bottom")))

R plot, x-axis and y-axis touching

My problem concerns the making of a graph for a publication in R. I have used the plot function like follows:
plot(x=data$SL, y=data$BD, xlab = "SL (mm)", ylab = "BD (mm)", pch=data$pch)
SL ranges from 51.7 to 73.7 and BD from 13.5 to 20.4. Unfortunately I am not allowed to post images yet.
However, wanting to get rid of the box I used "axes=F". Problem now is lack of control over the axis function. I used:
axis(side=1, lwd=3, xpd=TRUE, at=c(min(data$SL):max(data$SL)))
axis(side=2, lwd=3, xpd=TRUE, at=c(min(data$BD):max(data$BD)))
Problem is that I can't manage to get the y- and x-axis to come together on the same point as in the plot with the box. How to let the x- and y- axis to touch each other?
Most likely setting xaxs = "i" and yaxs = "i" will help you getting the desired behaviour.
plot(c(1,2,3),c(2,4,6),axes=F,xaxs = "i",yaxs="i",xlim=c(0,3),ylim=c(0,6))
axis(side=1, lwd=3, xpd=TRUE, at=0:3)
axis(side=2, lwd=3, xpd=TRUE, at=seq(0,6,2))
Try box(bty='L') to draw only the left and bottom parts of the box. You could also just draw the lines yourself using lines, segments, or abline and using grconvertX and grconvertY functions to find the locations where to draw the lines.
I suggest that you follow the procedure you outlined and then use:
box(which = "plot", bty = "l")
e.g.:
plot.new()
plot.window(xlim = c(1, 18), ylim = c(2, 20))
points(1:18, 2:19, pch = 1, col = "#FF7F24", cex = 1.2)
lines(1:18, 2:19, col = "#FF7F24", lwd = 2)
axis(side = 1,
lwd = 0,
lwd.ticks = 1,
at = 1:18,
cex.axis = 0.9)
title(main = "Plot",
ylab = "Y-Axis")
legend("top",
legend = c("Legend"),
col = c("#FF7F24"),
text.col = c("#FF7F24"),
pch = 1,
bty = "n",
cex = 1.2)
axis(side = 2,
lwd = 0,
lwd.ticks = 1)
box(which = "plot", bty = "l")
You should pass the options lwd = 0 and lwd.ticks = 1 to your seperate axis() calls in order to prevent some parts of your axes to appear fatter than other parts of your axis because some get overlayed by your call to box() and some do not.
The solution of using box() at the end is, I think, more general in that you can use it when e.g. you cannot or do not want to pass bty = "l" in your plot.default or plot.window call.

Resources