Search code examples
rdateposixct

Difference between "as.numeric" and "as.POSIXct.numeric" (only the first seems to work)?


I am struggling with as.POSIXct.numeric. The following code works:

dates <- structure(c(1649285787, 1651134684), class = c("POSIXct", "POSIXt"), 
                   tzone = "UTC")
lims <- as.numeric(dates)
limits <- as.POSIXct.numeric(lims, origin = as.POSIXct("1970-01-01", tz = "UTC"))
plot(stepfun(x = dates, # OK
             y = c(0, 1, 2)),
     do.points = FALSE)
plot(stepfun(x = dates, # OK 
             y = c(0, 1, 2)),
     do.points = FALSE, 
     xlim = lims)

However, the following fails and I don't understand why (I need to specify the limits):

plot(stepfun(x = dates, # Not OK
             y = c(0, 1, 2)),
     do.points = FALSE, 
     xlim = dates)
# Error in as.POSIXct.numeric(e) : 'origin' must be supplied
plot(stepfun(x = dates, # Not OK
             y = c(0, 1, 2)),
     do.points = FALSE, 
     xlim = limits)
# Error in as.POSIXct.numeric(e) : 'origin' must be supplied

Does anybody understand this behavior? I explicitly specified the origin in as.POSIXct.numeric(lims, origin = ...)!


Solution

  • The reason why the first chunk works is because stepfun(x = dates, y = c(0, 1, 2)) returns an object of class "stepfun" (you can check it by running class(stepfun(x = dates, y = c(0, 1, 2)))) and the plot method for stepfun objects will make a plot setting the X and Y axis as numerical. In other words, your first chunk works because the xlim was set as numerical (which is what plot method for stepfun objects expects). Conversely, when you set the xlim with a POSIX vector (dates or limits), the plot method simply does not what to do with them because it is expecting a numeric vector.

    If you need to change the axis labels, I suggest doing it externaly as follows:

    plot(stepfun(x = dates, 
                 y = c(0, 1, 2)),
         do.points = FALSE, 
         xlim = lims, axes = FALSE)
    
    xLabels <- pretty(limits)
    axis(side = 1, at = as.numeric(xLabels), labels = xLabels)
    axis(side = 2)
    box()
    

    pretty function is just a quickly way to find out vector of "pretty" (rounded) break points, but can use another way to set that values.