i've got a tiny problem in here, which i would like to have some hints on.
How can i change the space between ticks and labels? (indicated with 1 & 2)
my current structure looks as follows:
par(mfrow=c(5,2),oma=c(0,0,2,0),las=1,mar=c(3,5,2,1),cex.lab=0.9, cex.axis=0.7)
plot(sapply(ERRORS.train.fast[[1]],mean),main="Pipe 63569",type="l", ylab="", xlab="",xaxt="n")
axis(1, at=1:29,labels=seq(2,30,1))
title(ylab= "RMSE (-)",line=3)
title(xlab= "K-Value",line=2)
highly appreciate your help!
cheers,
Olli
You can use the padj argument for "adjustment for each tick label perpendicular to the reading direction." (from ?axis)
par(mfrow = c(1, 2))
plot(1:5, axes = F)
axis(1)
plot(1:5, axes = F)
axis(1, padj = -.75)
Unfortunately, the directions are different for the different axes (because it is relative what is "up" for the text), so to move the labels closer to the ticks, you will want lower padj values for the horizontal axis, but higher padj values for the vertical axis.
If you rotate the labels (as shown in your example plot on the vertical axis), you will use hadj instead of padj. Overall, I would expect you want something like:
plot(1:5, axes = F)
axis(1, padj = -.75)
axis(2, hadj = 0, las = 1)
You can use the mpg par.
par(mfrow=c(1,2))
plot(iris[,3:4], pch=20, col=rainbow(3)[iris$Species],
ylab="", xlab="",xaxt="n")
axis(1, at=1:7)
plot(iris[,3:4], pch=20, col=rainbow(3)[iris$Species],
ylab="", xlab="", xaxt="n")
axis(1, at=1:7, mgp=c(0,0.5,0))
Related
This question already has an answer here:
R Base Plot suppress axis line but show ticks
(1 answer)
Closed 2 years ago.
When I use box() with plot() and add some axes, the line where the tick marks are attached to the axes overlays with the box lines so you see a thickened line at the axis. How do you remove this overlap?
See code and diagram for more:
x <- seq(-pi,pi,0.1)
plot(x, sin(x), axes=FALSE)
axis(side=1, at=seq(-2, 1, by = 1))
axis(side=2, at=seq(-0.5, 0.5, by = 0.3))
box()
So you can see on the x and y axis there appears to be a thicker "double" line in the center, which just looks messy.
Note: I know one way to eliminate this problem is by making axes=TRUE, but I have a lot of specifications to add so I need to make axes=FALSE and then add axis() as a separate function.
You have to use col and col.ticks to get the desired output. Here is the code:
x <- seq(-pi,pi,0.1)
plot(x, sin(x), axes=FALSE)
axis(side=1, at=seq(-2, 1, by = 1), col = NA, col.ticks = 1)
axis(side=2, at=seq(-0.5, 0.5, by = 0.3), col = NA, col.ticks = 1)
box()
Now the plot doesn't have those double lines
Same issue has been discussed here. Thanks
I am having trouble getting the spacing right on a plot on top of a horizontal barplot. It is the same general issue as described here:
http://www.r-bloggers.com/adding-lines-or-points-to-an-existing-barplot/
But I am trying to use "plot" instead of "points" or "lines". Is there a trick for using plot to get the spacing of the bars and the points to match?
Code:
barplot(df$DIC_mM,col=scalegreen, xlab="DIC mM", horiz=TRUE, xlim=c(0,0.7),
col.axis="white", col.lab="white", axes=FALSE, border="white")
axis(1,line=1,col="white",col.ticks="white",col.axis="white")
par(new = TRUE)
plot(df$d13DIC,df$Order, type="p", axes = FALSE, bty = "n", xlab ="",
col="deepskyblue2", lwd=5, xlim=c(-50,170), lend=2, col.lab="white", ylab="")
axis(3,at = c(-50,0,50,100,150), line=1, col="deepskyblue2", col.ticks="deepskyblue2",
col.axis="deepskyblue2")
mtext(expression(paste(delta ^{13},'DIC'," \u0028","\u2030","\u0029")), 3,
line=-0.5,at=50,col="deepskyblue2", cex=0.75)
Is there a reason why you don't want to use points to add the points? If you're willing to use points you can do it like this:
Create barplot and save the y-coordinates of the bars to y. You haven't provided sample data, so I'll use the built-in mtcars data frame:
y = barplot(mtcars$mpg[1:10], horiz=TRUE)
Now add the points. We use y as the y values, because those are the coordinates of the midpoints of each bar:
points(sqrt(mtcars$mpg[11:20]), y, col="red", pch=16, cex=2)
When you use par(new=TRUE) and then call plot again, you're overlaying a new plot with a new coordinate system that in general will be different from the original coordinate system.
This is what worked, based on this post suggested by eipi10: midpoints returned by barplot function do not actually line up with midpoints of bars
mp<-barplot(df$DIC_mM,col=scalegreen, xlab="DIC mM", horiz=TRUE, xlim=c(0,0.7), col.axis="white", col.lab="white", axes=FALSE, border="white", ylim=c(0,length(df$DIC_mM)+2))
axis(1,line=1,col="white",col.ticks="white",col.axis="white")
par(new = TRUE)
plot(df$d13DIC, mp, type="p", axes = FALSE, bty = "n", xlab ="",col="deepskyblue2", lwd=5, xlim=c(-50,170), lend=2, col.lab="white", ylab="", ylim=c(0,length(df$DIC_mM)+2))
axis(3,at = c(-50,0,50,100,150),line=1,col="deepskyblue2",col.ticks="deepskyblue2",col.axis="deepskyblue2")
mtext(expression(paste(delta ^{13},'DIC'," \u0028","\u2030","\u0029")),3,line=-0.5,at=50,col="deepskyblue2", cex=0.75)
I have this code:
# Plotting everything
plot( p1, col= "lightgreen", xlim=c(-2.5,4.5), ylim=c(0, 700), main="Daily Total Precipitation for AR and Oct-May", xlab="ln(x)" , ylab="Frequency", xaxt = "n") # first histogram
plot( p2, col="red", xlim=c(-2.5,4.5), ylim=c(0, 700), xaxt = "n" , add=T)
# Adding in text labels on top of the bars
text(x, y, paste(round(percents,2),"%"), cex=0.50, pos=3, offset=0.3, col="black")
axis(side=1, at=breaks) # new x-axis
# parameter that needs to be set to add a new graph on top of the other ones
par(new=T)
plot(x, percents, xlim=c(-2.5,4.5), type="l", col="yellow", lwd=3.0, axes=F, ylab=NA, xlab=NA)
axis(side=4, at=seq(0,100,by=10), col="yellow", col.axis="yellow") # additional y-axis
mtext("Percent", side=4, col="yellow")
# legend settings
legend("topleft", c("AR", "Oct-May"), lwd=10, col=c("red", "lightgreen"))
Which produces this graph:
And I can't seem to figure out how to get the secondary y-axis label to show up in the correct position. Any help or suggestions is greatly appreciated.
Edit: Using RStudio.
One option is to specify the line argument to mtext(). In the example below I add a couple more lines to the right (side = 4) margin of the plot using par(), and then I draw three labels using mtext() at the default (line = 0), line 3 (line = 3), and line -3 (line = -3):
op <- par(mar = c(5,4,4,4) + 0.1)
plot(1:10)
mtext("line0", side = 4)
mtext("line3", side = 4, line = 3)
mtext("line-3", side = 4, line = -3)
par(op)
Note that line numbers increase away from the plot region and that negative line values move into the plot region, or to the left of the right boundary of the plot region.
It takes a little playing with the number of margin lines (as set in par(mar = x)) and which line you want to draw on using mtext(), but a little trial and error should get you what you want.
Note also that you don't need to specify integer values for the line argument. You can specify fractions of lines too: line = 2.5.
I need to break an axis from 0.5 to 1.5. My code is:
matplot( wxyz$days_until_last_pay, wxyz[,c(2,3,4,5)], type=c("b"), pch=1, col=1:4,
main="x![enter image description here][1]", cex.main=0.8)
legend("bottomright", inset=c(0,-0.57), fill=NULL,
legend = c("mean","median","max", "min"), col=1:4, pch=1, cex=0.8)
library("plotrix")
axis.break(axis=2,1,,2,style="zigzag", brw=0.03)
But I only get a line in it. This is not breaking the axis.
How can I solve this?
Thanks!
axis.break puts a break into an existing plot, so if the axis is not "broken" it will not work.
One suggestion is to make two plots on top of each other and set their ylim be so that there is a gap between 0.5 and 1.5, e.g.
## Some data, set.seed(1)
dat <- matrix(c(rnorm(50, 2, 0.1),
rnorm(50, 0.2, 0.05),
rnorm(50, 0.3, 0.05)),
byrow=FALSE, ncol=3)
## Split the device into two subplots
par(mfrow = c(2,1))
## Set the bottom margin of the top plot to 0.1
par(mar=c(0.1,4.1,4.1,2))
## Top plot (first column of the matrix)
plot(dat[,1], add=T, type="l", xaxt="n", ylab="", ylim=c(1.5, 2.5))
## Set the top margin of the bottom plot to 0.1
par(mar=c(5.1,4.1,0.1,2))
## Bottom plot
matplot(dat[,2:3], type="l", col=2:3, ylab="", ylim=c(0, 0.5))
This gives you something like:
I created a figure of two plots (two years) of climate data (temp and precip) that looks exactly like I want it, except that one of my axes has too many tick marks. With everything I have going on with this figure, I can't find a way to specify fewer tick marks without messing up other parts. I would also like to specify where the tick marks are. Here is the figure:
You can see that the tick marks for the top axis just blur together and the numbers chosen are not very meaningful to me. How can I tell R what I really want?
Here are the datasets I am using: cobs10 and
cobs11.
And here is my code:
par(mfrow=c(2,1))
par(mar = c(5,4,4,4) + 0.3)
plot(cobs10$day, cobs10$temp, type="l", col="red", yaxt="n", xlab="", ylab="",
ylim=c(-25, 30))
axis(side=3, col="black", at=cobs10$day, labels=cobs10$gdd)
at = axTicks(3)
mtext("Thermal Units", side=3, las=0, line = 3)
axis(side=2, col='red', labels=FALSE)
at= axTicks(2)
mtext(side=2, text= at, at = at, col = "red", line = 1, las=0)
mtext("Temperature (C)", side=2, las=0, line=3)
par(new=TRUE)
plot(cobs10$gdd, cobs10$precip, type="h", col="blue", yaxt="n", xaxt="n", ylab="",
xlab="")
axis(side=4, col='blue', labels=FALSE)
at = axTicks(4)
mtext(side = 4, text = at, at = at, col = "blue", line = 1,las=0)
mtext("Precipitation (cm)", side=4, las=0, line = 3)
par(mar = c(5,4,4,4) + 0.3)
plot(cobs11$day, cobs11$temp, type="l", col="red", yaxt="n", xlab="Day of Year",
ylab="", ylim=c(-25, 30))
axis(side=3, col="black", at=cobs11$day, labels=cobs11$gdd)
at = axTicks(3)
mtext("", side=3, las=0, line = 3)
axis(side=2, col='red', labels=FALSE)
at= axTicks(2)
mtext(side=2, text= at, at = at, col = "red", line = 1, las=0)
mtext("Temperature (C)", side=2, las=0, line=3)
par(new=TRUE)
plot(cobs11$gdd, cobs11$precip, type="h", col="blue", yaxt="n", xaxt="n", ylab="",
xlab="", ylim=c(0,12))
axis(side=4, col='blue', labels=FALSE)
at = axTicks(4)
mtext(side = 4, text = at, at = at, col = "blue", line = 1,las=0)
mtext("Precipitation (cm)", side=4, las=0, line = 3)
Thanks for thinking about it.
You've pretty much got the solution already:
axis(side=3, col="black", at=cobs10$day, labels=cobs10$gdd)
Except, you are asking to have ticks and labels at every single entry.
Take a look at the function pretty:
at <- pretty(cobs10$day)
at
# [1] 0 100 200 300 400
These are where the ticks should be placed on the x-axis. Now you need to find the corresponding labels. This is not straigtforward, but we will get:
lbl <- which(cobs10$day %in% at)
lbl
# [1] 100 200 300
lbl <- c(0, cobs10$gdd[lbl]
axis(side=3, at=at[-5], labels=lbl)
Update
I've been a bit annoyed by your use of three different series in a single plot. There are many reasons this is troublesome.
Having two y-values are always troublesome see this article from Stephen Few (go to page 5 for my favorite example); in your case it is not that serious due to the nature of the plots and your use of colours to indicate which y-axis the values belong to. But still, on principle.
Axis ticks should have a fixed function, e.g. linear or logarithm. With your Thermal Units, they appear "randomly" (I know that is not the case, but for an outsider they do).
We gotta do something about your x-axis ticks that just refer to "day of year".
First up, we take a look at your data and see what can be done naively. We recognize that your ''date'' variable is actual dates. Let's exploit it and make R aware of it!
cobs10 <- read.table('cobs10.txt',as.is=TRUE)
cobs10$date <- as.Date(cobs10$date)
plot(temp ~ date, data=cobs10, type='l')
Here, I really like the x-axis ticks and had some trouble replicating it. ''pretty'' on dates insisted on either 4 ticks or 12 ticks. But we will come back to that later.
Next, we can do something about the overlay plotting. Here I use ''par(mfrow=c(3,1))'' to instruct R to have three multiple plots stacked in a single window; with these multiple plots we can differentiate between inner and outer margins. The ''mar'' and ''oma'' arguments refers to the inner and outer margin.
Lets put all three variable together!
par(mfrow=c(3,1), mar=c(0.6, 5.1, 0, 0.6), oma=c(5.1, 0, 1, 0))
plot(temp ~ date, data=cobs10, type='l', ylab='Temperatur (C)')
plot(precip ~ date, data=cobs10, type='l', ylab='Precipitation (cm)')
plot(gdd ~ date, data=cobs10, type='l', ylab='Thermal units')
This looks okay, but not with ticks on top of the plots. Not good. Naturally, we can enable ticks in the first two plots (with ''plot(..., xaxt='n')''), but this will distort the bottom plot. So you will need to do so for all three plots and then add the axis to the outer plotting region.
par(mfrow=c(3,1), mar=c(0.6, 5.1, 0, 0.6), oma=c(5.1, 0, 1, 0))
plot(temp ~ date, data=cobs10, type='l', xaxt='n', ylab='Temperatur (C)')
plot(precip ~ date, data=cobs10, type='l', xaxt='n', ylab='Precipitation (cm)')
plot(gdd ~ date, data=cobs10, type='l', xaxt='n', ylab='Thermal units')
ticks <- seq(from=min(cobs10$date), by='2 months', length=7)
lbl <- strftime(ticks, '%b')
axis(side=1, outer=TRUE, at=ticks, labels=lbl)
mtext('2010', side=1, outer=TRUE, line=3, cex=0.67)
Since ''pretty'' doesn't behave as we want it to, we use ''seq'' to make the sequence of x-axis ticks. Then we format the dates to just display an abbreviation of the month name, but this is done with regard to local settings (I live in Denmark), see ''locale''.
To add the axis-ticks and a label to the outer region, we must remember to specify ''outer=TRUE''; otherwise it is added to the last subplot.
Also note that I specified ''cex=0.67'' to match the font size of the x-axis to the y-axis.
Now I agree that displaying the thermal units in a individual subplot is not optimal, although it is the correct way of displaying it. But there was the issue with the ticks. What we really want is to display some nice values that clearly display that they are not linear. But your data does not necessarily contain these nice values, so we will have to interpolate them ourselves.
For this, I use the ''splinefun''
lbl <- c(0, 2, 200, 1000, 2000, 3000, 4000)
thermals <- splinefun(cobs10$gdd, cobs10$date) # thermals is a function that returns the date (as an integer) for a requested value
thermals(lbl)
## [1] 14649.00 14686.79 14709.55 14761.28 14806.04 14847.68 14908.45
ticks <- as.Date(thermals(lbl), origin='1970-01-01') # remember to specify an origin when converting an integer to a Date.
Now the thermal ticks are in place, lets try it.
par(mfrow=c(2,1), mar=c(0.6, 5.1, 0, 0.6), oma=c(5.1, 0, 4, 0))
plot(temp ~ date, data=cobs10, type='l', xaxt='n', ylab='Temperatur (C)')
plot(precip ~ date, data=cobs10, type='l', xaxt='n', ylab='Precipitation (cm)')
usr <- par('usr')
x.pos <- (usr[2]+usr[1])/2
ticks <- seq(from=min(cobs10$date), by='2 months', length=7)
lbl <- strftime(ticks, '%b')
axis(side=1, outer=TRUE, at=ticks, labels=lbl)
mtext('2010', side=1, at=x.pos, line=3)
lbl <- c(0, 2, 200, 1000, 2000, 3000, 4000)
thermals <- splinefun(cobs10$gdd, cobs10$date) # thermals is a function that returns the date (as an integer) for a requested value
ticks <- as.Date(thermals(lbl), origin='1970-01-01') # remember to specify an origin when converting an integer to a Date.
axis(side=3, outer=TRUE, at=ticks, labels=lbl)
mtext('Thermal units', side=3, line=15, at=x.pos)
Update I changed the mtext function calls in the last code block to ensure that the x-axis texts are centred on the plotting region, not the entire region. You might want to tweak the vertical position by changing the line-argument.