1

I saw here that abline() does not work with xts plots. I typically use plot(as.zoo()) of xts objects and ran into the following problem. Let's first generate some dummy time series data (the definition of start and end turn out to be crucial):

library(xts)
start <- strptime("1888-01-01 00:30", format = "%Y-%m-%d %H:%M", tz = "UTC")
end   <- strptime("2019-12-31 00:10", format = "%Y-%m-%d %H:%M", tz = "UTC")
n <- 1000
dates <- seq(start, end, length.out = n)
set.seed(1)
dat <- rnorm(n)
ts <- xts(dat, order.by = dates)

Now let's try to plot ts as a zoo object and add lines:

plot(as.zoo(ts), type = "p")
abline(v = as.Date("1950-01-01"), col = "red") # not placed at the right location
abline(v = as.Date("2000-01-01"), col = "blue") # same (wrong) placement
abline(v = strptime("1950-01-01 00:00", format = "%Y-%m-%d %H:%M", tz = "UTC"), col = "green") # also fails

All abline() calls seem to plot in the same (wrong) location, why?

Remark: The following uses a different definition of start and end and that works as expected:

start. <- as.Date(start)
end. <- as.Date(end)
dates. <- seq(start., end., length.out = n)
ts. <- xts(dat, order.by = dates.)
plot(as.zoo(ts.), type = "p")
abline(v = as.Date("1950-01-01"), col = "red")
Marius Hofert
  • 6,546
  • 10
  • 48
  • 102
  • 1
    look at `axis(3)`, and you're mixing date with date-time objects `plot(as.zoo(ts), type = "p"); abline(v = as.numeric(strptime("1950-01-01 00:30", format = "%Y-%m-%d %H:%M", tz = "UTC")))` and `as.numeric(as.Date("1950-01-01"))` is approximately 0 on the scale of the x-axis – rawr Aug 25 '21 at 08:14
  • ... nice, thanks. Any chance to get `abline()` to draw at a given date-time object? – Marius Hofert Aug 25 '21 at 08:21
  • yes you just have to use `abline(v = as.numeric(...))` as in my example for some reason, i thought this would be automatic/coerced to numeric for you, but apparently not – rawr Aug 25 '21 at 08:28
  • Ah, I see, indeed, `abline(v = as.numeric(strptime("1950-01-01 00:30", format = "%Y-%m-%d %H:%M", tz = "UTC")))` works, thanks. Do you want to formulate this as an answer? – Marius Hofert Aug 25 '21 at 08:40

1 Answers1

1

There are several problems here:

  1. abline doesn't know what class you originally used on the X axis when the plot was created. It just takes the internal numeric value of whatever you give it. If you plot it using one class and use a different class in abline it is not going to work.

  2. In plotting and most other cases it is better to use POSIXct class rather than POSIXlt class. That is do NOT use strptime as it produces POSIXlt. Use as.POSIXct as it produces POSIXct. The internal form of a POSIXlt object is a list of 9 components which abline can't interpret in the desired way.

  3. Regarding the subject of the post this has nothing to do with zoo. abline works this way even without any packages. If you had used plot(dat ~ dates) then the abline command would have resulted in the same output.

Thus the code should be

library(xts)

fmt <- "%Y-%m-%d %H:%M"
start <- as.POSIXct("1888-01-01 00:30", format = fmt, tz = "UTC")
end   <- as.POSIXct("2019-12-31 00:10", format = fmt, tz = "UTC")
n <- 1000
dates <- seq(start, end, length.out = n)
set.seed(1)
dat <- rnorm(n)
ts <- xts(dat, order.by = dates)

plot(as.zoo(ts), type = "p")
v <- as.POSIXct("1950-01-01 00:00", format = fmt, tz = "UTC")
abline(v = v, col = "green")

screenshot

G. Grothendieck
  • 254,981
  • 17
  • 203
  • 341