Why is the last x-axis label omitted? - r

In the following example, the last x-axis label ("4.0") is omitted.
df <- data.frame(x = c(1, 2, 3.8), y = c(1, 2, 3))
#png(filename = "cutoff.png")
plot(df$x, df$y, xaxt = "n")
axis(side = 1, at = seq(0, 4, 0.5), labels = seq(0, 4, 0.5))
#dev.off()
How to prevent this behaviour?

You axis limit does not include 4; you need to overwrite the default limits of the plot (which it derives from the data) using xlim:
plot(df$x, df$y, xaxt = "n", xlim = c(1, 4))
Note that when using axis your specification of at will become your labels unless you overwrite that, so your script doesn't need to specify labels; your script can become:
axis(side = 1, at = seq(0, 4, 0.5))

As #griffinevo answered (+1), If you want the axis limits to go to 4, you must specify that using xlim. However, it is probably worth explaining how the default limits are computed. This is explained in the documentation, but in a slightly obscure place. On the help page ?par search for xaxs. There you will see
Style "r" (regular) first extends the data range by 4 percent at each
end and then finds an axis with pretty labels that fits within the
extended range.
In your case, the data ranges from 1 to 3.8. So plot will look for pretty labels inside the range
1 - 0.04*(3.8-1) = 0.888
to
3.8 + 0.04*(3.8-1) = 3.912
4 is outside of this range and so will not appear as an axis label. For completeness, it is worth noting that "pretty" sounds like just a word, but actually has a technical meaning here - related to the pretty function. If you look at the help page ?pretty You will see the description:
Compute a sequence of about n+1 equally spaced ‘round’ values which
cover the range of the values in x. The values are chosen so that they
are 1, 2 or 5 times a power of 10.
There is additional detail on the help page.

Related

Function `axis` behaves unexpectedly for noninteger values of parameter `mgp[3]`

?par says this about mgp[1:3]:
The margin line (in mex units) for the axis title, axis labels and axis line. Note that mgp[1] affects title whereas mgp[2:3] affect axis. The default is c(3, 1, 0).
?axis says something similar. However, it seems that tick labels are not in general placed at line mgp[2], but rather at line mgp[2] + (mgp[3] %% 1). Thus, axis seems to behave as documented only when mgp[3] is an integer. Is this a bug in axis, or is something else going on?
Here is an example showing expected and actual output of axis for integer and noninteger mgp[3]:
par(mar = c(5, 1, 5, 1))
plot.new()
plot.window(xlim = c(0, 1), ylim = c(0, 1))
box(lty = 3)
## 'axis' puts line and labels in right place when 'mgp[3]' is integer
mgp_bottom <- c(0, 2.5, 1) # 'mgp[1]' is arbitrary
axis(side = 1, mgp = mgp_bottom)
mtext(c("labels", "line"), side = 1, line = mgp_bottom[2:3])
## 'axis' puts line in right place when 'mgp[3]' is noninteger,
## but apparently not labels
mgp_top <- mgp_bottom - c(0, 0, 1e-3)
axis(side = 3, mgp = mgp_top)
mtext(c("labels", "line"), side = 3, line = mgp_top[2:3])
mtext("LABELS", side = 3, line = mgp_top[2] + (mgp_top[3] %% 1))
This does look like a bug. I think it happens here: https://github.com/wch/r-source/blob/6e61247f042985d5cb9f09034cb9e694a69082e0/src/library/graphics/src/plot.c#L944-L948 . In this context, gpptr(dd)->mgp[2] is the value of par("mgp")[3], and is a double. Here it's converted to an int, which loses the fractional part.
I don't really understand what the intention is in this calculation, so I'm not sure that simply changing lineoff to a double wouldn't cause problems elsewhere.
This has been reported to R's bugzilla, in PR#18194, i.e.,
https://bugs.r-project.org/show_bug.cgi?id=18194
and fixed in the R sources, svn 80947, now.

Matplot R manually labelling x-axis

I have a problem labelling my matplot x-axis row. So I have 1388 instances, but I want my X-axis to a custom labeling in the form of a sequence in dates.
My R code looks like this:
Dates <- seq(as.Date("2004/01/29"), as.Date("2009/07/31"), by = "quarter")
matplot(seq(1388), t(Alldata[1, ]), type = "l",
lwd = 1, lty = 1, col = 1:10, xlab = "Dates", ylab = "Strike",
main = paste("TEST"), xaxt='n')
axis(side = 1:23, at=1, labels = paste(Dates, 1:23))
Can anybody help me get the Dates into the x-axis?
I have tried using same method as this: Change axis labels with matplot in R
but it doesn't work.
AllData is from an excel file in which the first number of rows looks like this:
I think you have confused the way the function axis works. In answering below I will generate a random matrix to replace your Alldata which I don't have access to
Alldata <- t(as.matrix(rnorm(23)))
We can generate the plot again:
matplot(seq(23), Alldata[1, ], type = "l",
lwd = 1, lty = 1, col = 1:10, xlab = "Dates",
ylab = "Strike", main = paste("TEST"), xaxt='n')
Now, its import to know what the arguments to axis are. First
side this is literally the side of the the rectangle on which the plot is drawn. It is one of the numbers 1, 2, 3, 4 corresponding to bottom, left, top, right, respectively.
You want the axis to be on the bottom so we set this to 1.
Next, the at argument, is for where the tick marks should be drawn. So if you have 10 points on your line, and you set this value to 1:10 it will draw a tick mark at each point on the axis. If you set it to c(2,4,6,8,10) it will draw a mark at every second point on the axis. In your case you've set it to 1, which would draw only one tick. Although since the side was set to 1:23 none showed up.
labels This argument will label the ticks which are drawn. Ideally it should be a vector the same length as the at value. You can make sure that they are the same length by creating an index variable and using this as the at variable and to index the labels.
This gets us to:
index <- c(1,7,14,21)
axis(side = 1, at = index, labels = paste(Dates, 1:23)[index])
I think having a full range of dates would look cluttered. But you can drop the index and choose the below if you prefer:
axis(side = 1, at = 1:23, labels = paste(Dates, 1:23))

Rotate y axis TEXT labels in plot.zoo

I would like to rotate the labelling of the y-labs to horizontal and can't find an answer without ggplot.
Is there a way to rotate them in plot.zoo?
The labels I mean are those ones called Series 1:5 and I have outlined them in red.
data <- xts(matrix(rnorm(1000), ncol = 5), order.by = as.Date(1:200))
plot.zoo(data)
Use las=1 like this:
plot.zoo(data, las = 1)
Update
The question later clarified that it was referring to the ylab. plot.zoo uses mtext for that and hard codes it; however, we could hack it using trace:
library(xts)
trace(plot.zoo,
quote(mtext <- function(...) graphics::mtext(..., cex = 0.7, las = 1)))
plot.zoo(data, oma = c(6, 5, 5, 0))
untrace(plot.zoo)

Reduce the amount of y axis tick values in R (pirateplot)

Since I have updated R to version 3.5.2, my pirateplots (yarrr library) show more y axis ticks than before. Before they only showed ticks at full number values (1, 2, 3, etc., 1), but now they also show ticks at .5 values (1, 1.5, 2, 2.5, 3, etc., 2). This is despite the fact that the data and scripts are exactly the same as before.
Do you know how I can remove the .5 value ticks and make the plots look like they looked before?
I think the yaxt.y argument is what you're looking for as it allows you to override the default y axis construction.
Here's a plot using default arguments
pirateplot(weight ~ Diet, data = ChickWeight)
Original plot
Now with the yaxt.y argument
pirateplot(weight ~ Diet, data = ChickWeight, yaxt.y = seq(0, 400, 25))
Second version
You can also specify the grid line widths with gl.lwd:
pirateplot(weight ~ Diet, data = ChickWeight, yaxt.y = seq(0, 400, 25), gl.lwd = c(.5, 1.5), gl.col = "black")
Third version
Hope this helps!

Add vertical lines on non-numerical x-axis in R

I want to create a graph in R using the image()-function. My x-axis has non-numerical subdivisions. The axis is divided like this: "Arctic Ocean" - "North Atlantic Ocean" - etc.
How can I add vertical lines to this axis in order to separate different groups on my axis using the abline(v = [value]) function?
This is the code I used to create the image (which works fine):
dev.new()
par(mar = c(9,9,1,1), bg = "grey90")
n.bins <- 24
image(log10(data.stand), col = colorRampPalette(blues9)(n.bins), xaxt = "n", yaxt = "n", useRaster = F)
axis(side = 2, at = 0:(n.taxa.data - 1) / (n.taxa.data - 1), labels = colnames(data.by.tax), las = 1)
axis(side = 1, at = 0:(n.iho.obis - 1) / (n.iho.obis - 1), labels = rownames(data.by.tax), las = 2, cex.axis = 0.5)
I tried implementing the vertical lines using the abline() function, but it doesn't appear on the figure.
Now my question is: how do I implement it correctly in this code? And how can I also make it appear in the figure?
Cheers!!
Since you didn't provide x and y arguments to image but only a z matrix, it took by default seq(0,1,nrow(z)) and seq(0,1,ncol(z)) as x and y values. So your vertical lines will have to be expressed in the [0,1] range. Let's say your 10 first columns out of 100 are one group then abline(v=.1) should do the trick. Of course it may be more convenient for you to declare a x and a y directly so you'll have better control on it.

Resources