To get the label positions on the first of each month, we use substr
.
One way is to use two-month intervals as you have indicated. For this we may generate sequences 1, 2, 3, ... along the dates, using seq_along
, and look where they are zero in modulo 2 to get the subset IDs ids
. To get the month-year format we use format=
(see ?strftime
for options).
op <- par(mar=c(5, 5, 3, 7)) ## set par
plot(datereal, base9, type="l", lwd=2, col="blue", xaxt="n", xlab="Month",
ylab="Daily new cases")
which(substr(datereal, 9, 10) == "01")
labs <- datereal[substr(datereal, 9, 10) == "01"]
ids <- seq_along(labs)[(seq_along(labs) + 1) %% 2 == 0]
axis.Date(1, at=labs[ids], format="%b %y", cex.axis=.9)
par(op) ## reset par

Alternatively, you can rotate the text ninety degrees (but the first variant is nicer). This is possible using mtext
. We still need axis
to get the tick marks.
op <- par(mar=c(5, 5, 3, 7))
plot(datereal, base9, type="l", lwd=2, col="blue", xaxt="n", xlab="Month",
ylab="Daily new cases")
axis(1, at=labs, labels=FALSE)
mtext(strftime(labs, format="%b %y"), side=1, line=.75, at=labs, las=2, cex=.8)
par(op)

Note, you appear to be working with the Plot window and saving images by mouse click. If you rescale the window, the labels may disappear. A better choice is to use, for example, the png
device as explained in this answer
Data:
base9 <- 5e5*dnorm(seq(-2, 14, length=516), 10, 4)
datereal <- seq(as.Date("2020-02-01"), as.Date("2021-06-30"), "day")