R plot multiple line plots (3) against single bar plot - r

I'm trying to plot multiple line plots against a single bar plot (in this example it's grouped but doesn't have to be) but I'm running into some issues with left y-axis resizing in strange ways. It seems ok-ish when there are two lines, but then extends the axis out when there are more so the scale is wrong and doesn't line up with the bars.
I need to end up with a situation where I can customise the labels on both the left and right y-axes, hence the use of axis at the bottom of the code. In the real implementation I'll be dynamically using 'M' for million or 'K' for thousand on the left, and '%' on the right.
Any help would be very much appreciated.
x = c("a","b","c","d")
y= cbind(c(50,40,30,20), c(40,30,20,10))
y2 = c(0.80,0.65,0.75,0.50)
y3 = c(0.30,0.20,0.50,0.60)
y4 = c(0.20,0.30,0.40,0.45)
#
par(mar=c(5,8,3,5))
bp <- barplot(t(y), beside=TRUE, las=1, names.arg=x, axes=TRUE, ylim=c(0,max(y)+10), labels=c("0","10 M","20 M","30 M","40 M","50 M","60 M"))
xlim <- c(floor(min(bp)), ceiling(max(bp)))
#
par(new=T)
plot(colMeans(bp), y2, type="o", col="black", lwd=3, lty=1, xaxt="n", yaxt="n", xlab="", ylab="", xlim = xlim)
points(colMeans(bp), y2, pch=20)
par(new=T)
plot(colMeans(bp), y3, type="o", col="red", lwd=3, lty=1, xaxt="n", yaxt="n", xlab="", ylab="", xlim = xlim)
points(colMeans(bp), y3, pch=20)
par(new=T)
plot(colMeans(bp), y4, type="o", col="red", lwd=3, lty=1, xaxt="n", yaxt="n", xlab="", ylab="", xlim = xlim)
points(colMeans(bp), y4, pch=20)
axis(side=2, at=c(0,0.10,0.20,0.30,0.40,0.50,0.60), labels=c("0","10 M","20 M","30 M","40 M","50 M","60 M"), las=1, pos=0.555)
axis(side=4, pretty(c(0,max(y2))), ylim=c(0,max(y2)), col='black', ylab='', las=1 )

You can use the lines() argument for the second and third line, the everything works fine. Here is an example for the third Line:
#par(new=T)
lines(colMeans(bp), y4, type="o", col="red", lwd=3, lty=1)
points(colMeans(bp), y4, pch=20)

Related

The x-axis does not start from the y=0 line in R

I created a plot with the code below
mydata <- c(20,40,60,30,70) #put as an example
myrange <- range(mydata)
plot(mydata2, type="o", col="blue", axes=F, ann=F)
axis(2, las=1, at=0:myrange[2])
axis(1, at=1:5, lab=c("Mon","Tue","Wed","Thu","Fri"))
However, the x-axis does not start from the y=0 line. What should I do?
I put the example figure below:
if I understand correctly, the axis lines don't touch. This might help...
add xaxs and yaxs argument to your plot call:
mydata2 <- c(20,40,60,30,70)
plot(mydata2, type="o", col="blue", axes=F, xaxs = "i",yaxs="i",ann=F, ylim=c(0, max(mydata2)))
axis(2, las=1, at=0:range(mydata2)[2])
axis(1, at=1:5, lab=c("Mon","Tue","Wed","Thu","Fri"))

Why do I loose parts of the plot when exporting it as metafile?

I'm working with GLMs and therefore do some plots with the "visreg" package, and I also add usual plots to them. My script looks like this:
library(visreg)
visreg(model01, scale = "response", type="conditional",line=list(col="green"), ylim=c(0,1), xlim=c(0,400), rug=F, axes=F, ann=F)
par(new=T)
plot(data$x ~ data$y, ylim=c(0,1), xlim=c(0,400), col=rgb(0,100,50,50, maxColorValue=255), pch=19, cex=2, axes=F, ann=F)
par(new=T)
visreg(model02, scale = "response", type="conditional",line=list(col="red"), ylim=c(0,1), xlim=c(0,400), rug=F, axes=F, ann=F )
par(new=T)
plot(data$x ~ data$z, ylim=c(0,1), xlim=c(0,400), col=rgb(0,50,100,50, maxColorValue=255), pch=19, cex=2, las=1, xlab="label01", ylab="label02")
axis(1)
axis(2, las=1)
box()
col1 <- c(rgb(0,100,50, maxColorValue=155), rgb(0,50,100, maxColorValue=155))
legend (315, 1.05, legend=c("bla01", "bla02"), col=c("green","red"), y.intersp=1.3, cex=0.9, lty=1, lwd=2, bty="n")
legend (309, 1.06, legend=c("",""), col=col1, pch=19, y.intersp=1.2, bty="n")
The visreg() parts plot the regression model while the plot() parts plot the corresponding data. The whole plot looks the way I want it in RStudio, but when I export it as a metafile I loose the plot() parts of it (except the axis labels, they are still there). Does anybody know why that is and what I can do to export it all as a metafile?
Cheers,
Alex

Plotting multiple plots - rescaling of axes

I found, that axes were rescaled during multiple plotting using par(new=T) parameter.
An example to demonstrate this:
a <- seq(1,10, by = 0.25)
b <- sin(a)
c <- sin(2*a)+1
d <- sin(0.5*a)+2
df <- data.frame(a,b,c,d)
plot(df$a, df$b, type="l")
par(new=T)
plot(df$a, df$c, type="l", col="blue")
par(new=T)
plot(df$a, df$d, type="l", col="red")
This is the result.
Instead of real scales, I have a transformed curves.
And this is the real result:
I used parameters axes=F, xlab="", ylab="" and did not see this "rescaling".
I find it very dangerous, that it is so easy to transform the data during plotting if you do not control y-limits.
Are there better ways to control y-limits than looking for min and max values in all plotted data to avoid this "rescaling" effect?
I have several quite big files and each of them gives only one line from 10 in one plot and I have several plots on one page to compare my data.
The code for the last "correct" image:
plot(df$a, df$b, type="l", ylim=c(-1.5,3.5))
par(new=T)
plot(df$a, df$c, type="l", ylim=c(-1.5,3.5), col="blue", axes=F, xlab="", ylab="")
par(new=T)
plot(df$a, df$d, type="l", ylim=c(-1.5,3.5), col="red", axes=F, xlab="", ylab="")
#Create an empty plot with enough xlim and ylim to accomodate all data
plot(1, 1, xlim = range(df[,1]), ylim = range(df[,-1]), type = "n", ann = FALSE)
#Draw the three lines
lines(df$a, df$b)
lines(df$a, df$c, col="blue")
lines(df$a, df$d, col="red")

"axis" won't add x-axis to boxplot

I'm trying to make a boxplot with custom axis labels, but I can't seem to add an x-axis to the plot.
For example:
test <- data.frame(year=as.integer(rep(1963:2014, each=10)),
response=rnorm(520))
boxplot(response~year, data=test, ylim=c(-3,3), xlab="", ylab="",
range=0, xaxt="n", yaxt="n")
responselabs <- as.numeric(c(-3:3, by=1))
yearlabs <- as.integer(seq(1965,2015, by=5))
axis(2, at=responselabs, tck=0.03, las=1)
axis(1, at=yearlabs, tck=0.03)
returns the boxplot, but no x-axis labels:
Trying to hack it the other way by making an empty plot first, I can get the axes, but it won't add the boxplot:
plot(NA, ylim=c(-3, 3), xlim=c(1962, 2015), xaxt="n", yaxt="n", ylab="", xlab="")
axis(2, at=responselabs, tck=0.03, las=1)
axis(1, at=yearlabs, tck=0.03)
boxplot(response~year, data=test, ylim=c(-3,3), xlab="", ylab="",
range=0, xaxt="n", yaxt="n", add=T)
What's going on here?
I think what's happening is that boxplot converts year to a factor. We can get around this by using the labels argument in axis:
boxplot(response~year, data=test, ylim=c(-3,3), xlab="", ylab="",
range=0, xaxt="n", yaxt="n")
responselabs <- as.numeric(c(-3:3, by=1))
yearlabs <- as.integer(seq(1965,2015, by=5))
axis(2, at=responselabs, tck=0.03, las=1)
axis(1, at = yearlabs - 1962, labels = yearlabs)
Why not use ggplot2?
library(ggplot2)
p<-ggplot(test,aes(x=year,y=response,group=year))+
geom_boxplot()+
scale_x_continuous(breaks=round(seq(min(test$year),max(test$year),by=5),1))
If you want to be rounded to the nearest 5 then the code is fairly easy to adjust in the scale_x_continuous() argument.
p<-ggplot(test,aes(x=year,y=response,group=year))+
geom_boxplot()+
scale_x_continuous(breaks = round(seq(round(min(test$year)/5,0)*5,round(max(test$year)/5,0)*5, by = 5),1))
Like others have stated, you may have confused the values underlying the x-axis. Playing around with abline() reveals that abline(v=2010) does not show up, but something like abline(v=50) will show up.
Here's a plot you're after, I believe (with some extra modifications):
year_vals <- as.integer(rep(1963:2014, each=10)) # pulling out of next line for easy reference
test <- data.frame(year=year_vals,response=rnorm(520))
boxplot(response~year, data=test, ylim=c(-3,3), xlab="", ylab="", range=0, xaxt="n", yaxt="n")
responselabs <- as.numeric(c(-3:3, by=1))
yearlabs <- year_vals[year_vals%%5==0] # alternate, more general definition; note that 2015 wasn't in the original 'test' data.frame #as.integer(seq(1965,2015, by=5))
axis(2, at=responselabs, tck=0.03, las=1)
# axis(1, at=1:length(yearlabs), tck=0.03)
axis(1, at=which(unique(year_vals)%in%yearlabs), labels=unique(yearlabs), tck=0.03)

How to plot horizontal y label

I tried to plot a horizontal y label using the following code:
require(grDevices)
par(mfrow=c(2,1), mar=c(0,3,0,0.5)+0.1, oma=c(3,0,0.5,0)+0.1,
mgp=c(2,1,0), cex=tcex)
par(las=1)
#pl-d001
plot(1, type="n", yaxt='n', xaxt='n', xaxs="i", yaxs="i", xlab="xlabel",
ylab=expression("axis "*italic(r[infinity])), xlim=c(0, 0.4), ylim=c(0, 1))
But, I only get a normal (vertical) Y label. What is wrong here?
As #rawr said in the comments, your best chance is with mtext:
plot(1, type="n", yaxt='n', xaxt='n', xaxs="i", yaxs="i",
xlab="xlabel", ylab="", xlim=c(0, 0.4), ylim=c(0, 1))
mtext(expression("axis "*italic(r[infinity])),side=2,las=1,line=1)
The reason why you can't do that directly from plot is that, internally, plot uses title to draw those labels and title (for some reason) doesn't take las or srt as arguments.

Resources