I have a problem in correctly plotting the labels of the following graph:
scatterhist = function(x, y, xlab="", ylab=""){
zones=matrix(c(2,0,1,3), ncol=2, byrow=TRUE)
layout(zones, widths=c(4/5,1/5), heights=c(1/5,4/5))
xhist = hist(x, plot=F, breaks=10)
yhist = hist(y, plot=F, breaks=10)
top = max(c(xhist$counts, yhist$counts))
par(mar=c(3,3,1,1))
plot(x, y)
par(mar=c(0,3,1,1))
barplot(xhist$counts, axes=FALSE, ylim=c(0, top), space=0)
par(mar=c(3,0,1,1))
barplot(yhist$counts, axes=FALSE, xlim=c(0, top), space=0, horiz=TRUE)
par(oma=c(3,3,0,0))
mtext(xlab, side=1, line=1, outer=TRUE, adj=0,
at=.8 * (mean(x)-min(x))/(max(x)-min(x)))
mtext(ylab, side=2, line=1, outer=TRUE, adj=0,
at=.8 * (mean(y)-min(y))/(max(y)-min(y)))
}
When I type:
scatterhist(x[,6], x[,7], xlab="Cost of Taxi", ylab="Cost of Fuel")
the labels overlap with the axes values. However, if I type:
scatterhist(x[,6], x[,7], xlab="Cost of Taxi", ylab="Cost of Fuel")
scatterhist(x[,6], x[,7], xlab="Cost of Taxi", ylab="Cost of Fuel")
the second graph is correctly displayed... Can anyone help me with this issue? I have also tried to open the graph window through windows() before the first plot, but this doesn't work...
Thanks! Stefano
Your par(oma=c(3,3,0,0)) line should come before the first par(mar=...) call since it should be applied to the whole device region (i. e. you can't change the size of the outer margin if you already plotted some graphs).
scatterhist = function(x, y, xlab="", ylab=""){
zones=matrix(c(2,0,1,3), ncol=2, byrow=TRUE)
layout(zones, widths=c(4/5,1/5), heights=c(1/5,4/5))
par(oma=c(3,3,0,0))
xhist = hist(x, plot=F, breaks=10)
yhist = hist(y, plot=F, breaks=10)
top = max(c(xhist$counts, yhist$counts))
par(mar=c(3,3,1,1))
plot(x, y)
par(mar=c(0,3,1,1))
barplot(xhist$counts, axes=FALSE, ylim=c(0, top), space=0)
par(mar=c(3,0,1,1))
barplot(yhist$counts, axes=FALSE, xlim=c(0, top), space=0, horiz=TRUE)
mtext(xlab, side=1, line=1, outer=TRUE, adj=0,
at=.8 * (mean(x)-min(x))/(max(x)-min(x)))
mtext(ylab, side=2, line=1, outer=TRUE, adj=0,
at=.8 * (mean(y)-min(y))/(max(y)-min(y)))
}
Related
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.
My legend is cropped in my plot. To solve this, I know I have to deal with margins but I do not know how. And the use of xpd=TRUE does not seems to work.
My code has this structure:
plot(x,y1)
par(new=TRUE)
plot(x,y2)
par(new=TRUE)
plot(x,y3)
...
par(xpd=TRUE)
legend(...)
The entire code:
time<-c(18,19, 21, 25, 26)
layer_0<-c(0.73,0.78,0.95,0.83,0.77)
layer_0_sd<-c(0.04,0.04,0.03,0.13,0.19)
layer_1<-c(0.89,0.9,0.61,0.28,0.08)
layer_1_sd<-c(0.03,0.01,0.14,0.14,0.09)
layer_2<-c(0.66,0.6,0.21,0.01,0)
layer_2_sd<-c(0.06,0,0.12,0.01,0)
layer_3<-c(0.23,0.13,0.05,0,0)
layer_3_sd<-c(0.07,0,0.03,0,0)
layer_4<-c(0.03,0.01,0.01,0,0)
layer_4_sd<-c(0.01,0,0.01,0,0)
layer_5<-c(0,0,0,0,0)
layer_5_sd<-c(0,0,0,0,0)
epsilon=0.02
plot(time, layer_0, ylim=c(0,1), type="o", lty=1, lwd=2,ylab="Longitudinal fCOVER", xlab="Days after seeding", cex.lab=1.5, cex.axis=1.5, cex.main=1.5, cex.sub=1.5)
segments(time, layer_0-layer_0_sd,time, layer_0+layer_0_sd, lwd=2)
segments(time-epsilon,layer_0-layer_0_sd,time+epsilon,layer_0-layer_0_sd, lwd=2)
segments(time-epsilon,layer_0+layer_0_sd,time+epsilon,layer_0+layer_0_sd, lwd=2)
for (i in c(1:5)){
par(new=TRUE)
eval(parse(text=paste("plot(time, layer_",i,", ylim=c(0,1), type='o', xlab='', ylab='', xaxt='n', yaxt='n',lwd=2, lty=",i+1,", col=",i+1,")+
segments(time, layer_",i,"-layer_",i,"_sd,time, layer_",i,"+layer_",i,"_sd, col=",i+1,",lwd=2)+
segments(time-epsilon,layer_",i,"-layer_",i,"_sd,time+epsilon,layer_",i,"-layer_",i,"_sd, col=",i+1,",lwd=2)+
segments(time-epsilon,layer_",i,"+layer_",i,"_sd,time+epsilon,layer_",i,"+layer_",i,"_sd, col=",i+1,",lwd=2)", sep="")))
}
par(xpd=TRUE)
legend(x=17.65, y=1.3, c("0-5 cm","5-10 cm", "10-15 cm", "15-20 cm", "20-25 cm","25-30 cm"), lty=c(1,2,3,4,5,6), col=c(1,2,3,4,5,6),ncol=3, lwd=2, cex=1.5)
Just as an alternative, the use of the parameter inset makes this very easy. A similar duscussion can be found here.
for your example:
par(mar=c(5, 5, 6, 3), xpd=TRUE)
plot(time, layer_0, ylim=c(0,1), type="o", lty=1, lwd=2,ylab="Longitudinal fCOVER", xlab="Days after seeding", cex.lab=1.5, cex.axis=1.5, cex.main=1.5, cex.sub=1.5)
segments(time, layer_0-layer_0_sd,time, layer_0+layer_0_sd, lwd=2)
segments(time-epsilon,layer_0-layer_0_sd,time+epsilon,layer_0-layer_0_sd, lwd=2)
segments(time-epsilon,layer_0+layer_0_sd,time+epsilon,layer_0+layer_0_sd, lwd=2)
for (i in c(1:5)){
par(new=TRUE)
eval(parse(text=paste("plot(time, layer_",i,", ylim=c(0,1), type='o', xlab='', ylab='', xaxt='n', yaxt='n',lwd=2, lty=",i+1,", col=",i+1,")+
segments(time, layer_",i,"-layer_",i,"_sd,time, layer_",i,"+layer_",i,"_sd, col=",i+1,",lwd=2)+
segments(time-epsilon,layer_",i,"-layer_",i,"_sd,time+epsilon,layer_",i,"-layer_",i,"_sd, col=",i+1,",lwd=2)+
segments(time-epsilon,layer_",i,"+layer_",i,"_sd,time+epsilon,layer_",i,"+layer_",i,"_sd, col=",i+1,",lwd=2)", sep="")))
}
legend("top", inset = c(0, -0.25), legend=c("0-5 cm","5-10 cm", "10-15 cm", "15-20 cm", "20-25 cm","25-30 cm"), lty=c(1,2,3,4,5,6), col=c(1,2,3,4,5,6),ncol=3, lwd=2, cex=1.5)
If I have to place a legend outside a plot I generally do it with a separate panel, as I find it much easier to control positions and sizes then.
layout(1:2, heights=c(1, 5))
# Legend panel
par(mar=rep(0,4))
plot(0, 0, type="n", ann=FALSE, axes=FALSE)
legend("center", c("5-10 cm", "15-20 cm", "25-30 cm"), horiz=TRUE,
lty=2:4, col=1:3)
# Plot panel
par(mar=c(5,4,0,2))
plot(1:20, cumsum(rnorm(20)))
Or if you want to follow the theme you started using par(new=TRUE) you could do this
par(mar=c(5,4,5,2))
plot(1:20, cumsum(rnorm(20)))
par(new=TRUE, mar=c(0,0,1,0))
plot(0, 0, type="n", ann=FALSE, axes=FALSE)
legend("top", c("5-10 cm", "15-20 cm", "25-30 cm"), horiz=TRUE,
lty=2:4, col=1:3)
Both give the result below.
I have 3 sets of data that I am trying to plot on a single plot. The first data set x values range from ~ 1 to 1700 whereas the other two data sets x values are less than 20. Therefore I want to plot them on a log axis to show variations in all the data sets. However I do not want to transform the data as I want to be able to read the values off the graph. The x axis labels I would like are 1, 10, 100 and 1000 all equally spaced. Does anyone know how to do this? I can only find examples where the data is log as well as the axis. I have attached the code I am currently using below:
Thanks in advance for any help given.
Holly
Stats_nineteen<-read.csv('C:/Users/Holly/Documents/Software Manuals/R Stuff/Stats_nineteen.csv')
attach(Stats_nineteen)
x<-Max
x1<-Min
x2<-Max
y1<-Depth
y2<-Depth
par(bg="white")
par(xlog=TRUE)
plot(x2,y1, type="n", ylim=c(555,0), log="x", axes=FALSE, ann=FALSE)
box()
axis(3, at=c(1,10,100,1000), label=c(1,10,100,1000), pos=0, cex.axis=0.6)
axis(1, at=c(1,10,100,1000), label=c(1,10,100,1000), cex.axis=0.6)
axis(2, at=c(600,550,500,450,400,350,300,250,200,150,100,50,0), label=c
(600,"",500,"",400,"",300,"",200,"",100,"",0), cex.axis=0.6)
mtext("CLAST SIZE / mm", side=3, line=1, cex=0.6, las=0, col="black")
mtext("DEPTH / m", side=2, line=2, cex=0.6, las=0, col="black")
grid(nx = NULL, ny = NULL, col = "lightgray", lty = "solid",
lwd = par("lwd"), equilogs = TRUE)
par(new=TRUE)
lines(x1,y1, col="black", lty="solid", lwd=1)
lines(x2,y2, col="black", lty="solid", lwd=1)
polygon(c(x1,rev(x2)), c(y1,rev(y2)), col="grey", border="black")
par(new=TRUE)
plot(x=Average,y=Depth, type="o",
bg="red", cex=0.5, pch=21,
col="red", lty="solid",
axes=FALSE, xlim=c(0,1670), ylim=c(555,0),
ylab = "",xlab = "")
par(new=TRUE)
plot(x=Mode,y=Depth, type="o",
bg="blue", cex=0.5, pch=21,
col="blue", lty="solid",
axes=FALSE, xlim=c(0,1670), ylim=c(555,0),
ylab = "",xlab = "")
You can do this in ggplot using scale_x_log
so something like:
myplot <- ggplot( StatsNinetee,
aes (x = myResponse,
y = myPredictor,
groups = myGroupingVariable) ) +
geom_point() +
scale_x_log()
myplot
also, avoid attach() it can give odd behavior.
I'm having the code as like below. But I'm not getting all the x axis labels and it is not displaying in 45 degree when I try to have this in pdf. Since I'm new, Please help me correct this option.
pdf(file="figure.pdf", height=3.5, width=5, onefile=TRUE)
Runtime <- c(579,0,581,610,830,828,592,651,596,596,591,581,587,594,604,606,447,434,445)
Runtime
g_range <- range(0,Runtime)
g_range
plot(Runtime, type="o", col="blue", ylim=g_range,axes=FALSE, ann=FALSE)
lab=c('2011-07-20','2011-08-03','2011-08-10','2011-08-17','2011-08-24','2011-08-25','2011-08-27','2011-08-31','2011-09-07','2011-09-10','2011-09-14','2011-09-21','2011-09-28','2011-10-05','2011-10-06','2011-10-07','2011-10-13','2011-10-19','2011-10-31')
box()
lab
axis(1, at=1:19, lab=F)
text(axTicks(1), par("usr")[3] - 2, srt=45, adj=1, labels=lab, xpd=T, cex=0.8)
axis(2, las=1, at=500*0:g_range[2])
title(main="Runtime", col.main="red", font.main=4)
title(xlab="Build", col.lab=rgb(0,0.5,0))
title(ylab="MS", col.lab=rgb(0,0.5,0))
legend(1, g_range[2], c("AveElapsedTime"), cex=0.8, col=c("blue"), pch=21, lty=1);
dev.off()
When I run your code, I do not get the image you show. The problem is this line:
text(axTicks(1), par("usr")[3] - 2, srt=45, adj=1, labels=lab, xpd=T, cex=0.8)
as axTicks(1) returns:
> axTicks(1)
[1] 5 10 15
So what is happening is that your 19 labels are being plotted at those 3 locations.
If you want to plot at the locations of the ticks (1:19) then:
text(1:19, par("usr")[3] - 2, srt=45, adj=1, labels=lab, xpd=T, cex=0.8)
will work.
Here is a full example based on your code.
Runtime <- c(579,0,581,610,830,828,592,651,596,596,591,581,587,
594,604,606,447,434,445)
g_range <- range(0,Runtime)
lab <- c('2011-07-20','2011-08-03','2011-08-10','2011-08-17','2011-08-24',
'2011-08-25','2011-08-27','2011-08-31','2011-09-07','2011-09-10',
'2011-09-14','2011-09-21','2011-09-28','2011-10-05','2011-10-06',
'2011-10-07','2011-10-13','2011-10-19','2011-10-31')
## plot
op <- par(mar = c(6,4,4,2) + 0.1) ## bigger bottom margin
plot(Runtime, type="o", col="blue", ylim=g_range, axes=FALSE, ann=FALSE)
box()
axis(1, at=1:19, lab=FALSE)
text(1:19, par("usr")[3] - 40, srt=45, adj=1.2, labels=lab, xpd=T, cex=0.7)
axis(2, las=1, at=500*0:g_range[2])
title(main="Runtime", col.main="red", font.main=4)
title(xlab="Build", col.lab=rgb(0,0.5,0), line = 4.5)
title(ylab="MS", col.lab=rgb(0,0.5,0))
legend("topright", c("AveElapsedTime"), cex=0.8, col=c("blue"), pch=21, lty=1)
## reset par
par(op)
This might be better handled using function in the gridBase package though, which allows grid and base graphics to intermingle. The reason I say it might be better is that you can specify that the y coordinate be set in terms of numbers of lines rather that trying to work out a suitable value for y in terms of the plotted data.
Here is an example:
## load gridBase
require(gridBase)
## do the base plot parts
op <- par(mar = c(6,4,4,2) + 0.1) ## bigger bottom margin
plot(1:19, Runtime, type="o", col="blue", ylim=g_range, axes=FALSE, ann=FALSE)
box()
axis(1, at=1:19, lab=FALSE)
axis(2, las=1, at=500*0:g_range[2])
title(main="Runtime", col.main="red", font.main=4)
title(xlab="Build", col.lab=rgb(0,0.5,0), line = 4.5)
title(ylab="MS", col.lab=rgb(0,0.5,0))
legend("topright", c("AveElapsedTime"), cex=0.8, col=c("blue"), pch=21, lty=1)
## at this point, DO NOT alter the dimensions of the plotting window
## now do the grid business
vps <- baseViewports()
pushViewport(vps$inner, vps$figure, vps$plot)
## this adds the text
grid.text(lab, x = unit(1:19, "native"), y = unit(-1, "lines"),
just = "right", rot = 60, gp = gpar(cex = 0.7))
## this finishes off the viewport - you have to do this or things will go wrong:
popViewport(3)
## reset par
par(op)
Note this can be a bit picky on screen, rerunning the gridBase example on my R 2.13.2 install doesn't produce any labels. Closing the device and then running the code afresh works though. I don't think this should be a problem if you are drawing to a pdf() device.
When I try to give the title name as a function argument for Z and for legend, it is not working.. I also tried by just giving z. Please advise..
drawGraph <- function(x, y, z) {
g_range <- range(0,x)
plot(x, type="o", col="blue", ylim=g_range,axes=FALSE, ann=FALSE)
box()
axis(1, at=1:19, lab=FALSE)
text(1:19, par("usr")[3] - 2, srt=45, adj=1.2, labels=y, xpd=T, cex=0.3)
axis(2, las=1, at=500*0:g_range[2])
main_title<-as.character(z)
title(main=main_title, col.main="red", font.main=4)
title(xlab="Build", col.lab=rgb(0,0.5,0))
title(ylab="MS", col.lab=rgb(0,0.5,0))
legend("topright", g_range[2], c("z"), cex=0.8, col=c("blue"), pch=21, lty=1);
}
drawGraph(AET, lab, AveElapsedTime)
If you wanted to construct a title outside of the function you could use an as.expression(z). This would let the title be "The average time with ranges: 1 to 8" and the values in the range would be adjusted "on the fly".
drawGraph <- function(x, y, z) {
g_range <- range(0,x)
plot(x, type="o", col="blue", ylim=g_range,axes=FALSE, ann=FALSE)
box()
axis(1, at=1:19, lab=FALSE)
text(1:19, labels=y,par("usr")[3] - 2, srt=45, adj=1.2, xpd=T, cex=0.3)
axis(2, las=1, at=500*0:g_range[2])
main_title<-as.expression(z)
title(main=main_title, col.main="red", font.main=4)
title(xlab="Build", col.lab=rgb(0,0.5,0))
title(ylab="MS", col.lab=rgb(0,0.5,0))
legend("topright", g_range[2], c("z"), cex=0.8, col=c("blue"), pch=21, lty=1);
}
x <- rpois(19, 4)
AveElapsedTime=paste("The average time with ranges:",
round(range(x)[1], 3),
"to" , round(range(x), 3)[1])
lab=1:19
drawGraph(AET, lab, AveElapsedTime)
Is AveElapsedTime a variable? If yes,this works:
AveElapsedTime <- 50
drawGraph(AET, lab, AveElapsedTime)
If it's just text, this works:
drawGraph(AET, lab, "AveElapsedTime")
Quote AveElapsedTime so that it's treated as a string and not a variable:
drawGraph(AET, lab, "AveElapsedTime")