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)
Related
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"))
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
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.
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)
I need a two y-axes figure. hrbrmstr suggested to use simple plots. But when adapting the graph to my setting I observed I cannot add the ylab on the right hand side, getting a wired error:
Error in axis(4, ylim = c(0, 1), col = "black", col.axis = "black", las = 1, :
'labels' is supplied and not 'at'
Is this avoidable?
look at the code the bottom line fpr SOURCE OF ERROR
featPerf <- data.frame( expS=c("1", "2", "3", "4"),
exp1=c(1000, 0, 0, 0),
exp2=c(1000, 5000, 0, 0),
exp3=c(1000, 5000, 10000, 0),
exp4=c(1000, 5000, 10000,20000),
accuracy=c(0.4, 0.5, 0.65, 0.9) )
# make room for both axes ; adjust as necessary
par(mar=c(5, 5, 5, 7) + 0.2)
# plot the bars first with no annotations and specify limits for y
#barplot(as.matrix(featPerf[,2:5]), axes=FALSE, xlab="", ylab="", ylim=c(0, max(colSums(featPerf[2:5]))))
barplot(as.matrix(featPerf[,2:5]), axes=FALSE, xlab="", ylab="", beside=TRUE)
# make the bounding box (or not...it might not make sense for your plot)
#box()
# now make the left axis
axis(2, ylim=c(0, max(colSums(featPerf[2:5]))), col="black", las=1)
# start a new plot
par(new=TRUE)
# plot the line; adjust lwd as necessary
plot(x=1:4, y=featPerf[,6], xlab="Experiments", ylab="Abs. # of Features", axes=FALSE, type="l", ylim=c(0,1), lwd=5)
# annotate the second axis -- SOURCE OF ERROR -> VVVVVVVVVVVVVVVVVV
axis(4, ylim=c(0,1), col="black", col.axis="black", las=1, labels="Accuracy")
Like this?
par(mar=c(4,4,1,4) + 0.2)
barplot(as.matrix(featPerf[,2:5]), axes=FALSE, xlab="", ylab="", beside=TRUE)
axis(2, ylim=c(0, max(colSums(featPerf[2:5]))), col="black", las=1)
par(new=TRUE)
plot(x=1:4, y=featPerf[,6], xlab="Experiments", ylab="Abs. # of Features", axes=FALSE, type="l", ylim=c(0,1), lwd=5, col="blue")
axis(4, ylim=c(0,1), col="blue", col.axis="blue", las=1)
mtext("Accuracy",4,line=2, col="blue")
For the record, it is never a good idea to stack plots on top of each other this way (with two axes). I've made the line and the axis the same color in an attempt to draw attention to what you are doing, but this is still a very bad idea.
First of all it is not advisable to use two Y-axes in a same plot.
If you add at argument to the axis call, you get the name "Accuracy" on the right hand side of the plot.
axis(4, ylim=c(0,1), col="black", col.axis="black", las=1, labels="Accuracy",
at = .5)