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 = ...)
!
CodePudding user response:
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.
CodePudding user response:
We might try to hack the plot.stepfun
function by doing some date conversion stuff from line 30 on. More specifically we convert the xlim=
in "POSIXt"
format to a seq
uence of dates and use it in line 63 as values for the axis
.
plot_stepfun <- function(x, xval, xlim, ylim=range(c(y, Fn.kn)), xlab="x",
ylab="f(x)", main=NULL, add=FALSE, verticals=TRUE,
do.points=(n < 1000), pch=par("pch"), col=par("col"),
col.points=col, cex.points=par("cex"), col.hor=col,
col.vert=col, lty=par("lty"), lwd=par("lwd"), ...) {
if (!is.stepfun(x)) {
if (is.numeric(x)) {
sarg <- substitute(x)
x <- ecdf(x)
attr(x, "call") <- call("ecdf", sarg)
}
else stop("'plot.stepfun' called with wrong type of argument 'x'")
}
if (missing(main)) {
cl <- attr(x, "call")
main <- if (is.null(cl)) sys.call() else cl
}
knF <- knots(x)
xval <- if (missing(xval))
knF
else sort(xval)
if (missing(xlim)) {
rx <- range(xval)
dr <- if (length(xval) > 1L)
max(0.08 * diff(rx), median(diff(xval)))
else abs(xval)/16
xlim <- rx dr * c(-1, 1)
}
else {
xlim1 <- xlim
xlim <- as.numeric(xlim)
if (inherits(xlim1, c('Date', "POSIXt"))) {
tz <- attributes(as.POSIXlt(xlim1))$tzone
xlim2 <- as.POSIXct(paste(strftime(xlim1, '%F')), tz=tz[length(tz)])
if (as.numeric(difftime(xlim2[2], xlim2[1], units='secs')) < 86400) {
stop('will be implemented soon :)')
} else {
xseq <- seq.POSIXt(xlim2[1], xlim2[2], by='days')
if (length(xseq) > 6) {
xseq <- xseq[(seq_along(xseq) - 5) %% ceiling(length(xseq)/6) == 0]
}
}
}
dr <- diff(xlim)
}
xval <- xval[xlim[1L] - dr <= xval & xval <= xlim[2L] dr]
ti <- c(xlim[1L] - dr, xval, xlim[2L] dr)
ti.l <- ti[-length(ti)]
ti.r <- ti[-1L]
y <- x(0.5 * (ti.l ti.r))
n <- length(y)
Fn.kn <- x(xval)
dev.hold()
on.exit(dev.flush())
if (add)
segments(ti.l, y, ti.r, y, col=col.hor, lty=lty,
lwd=lwd, ...)
else {
if (missing(ylim))
ylim <- range(c(y, Fn.kn))
plot(NA, NA, type="n", xlim=xlim, ylim=ylim, xlab=xlab,
ylab=ylab, main=main, xaxt='n', ...)
if (exists('xseq')) {
axis(1, xseq, xseq)
} else {
axis(1, at=axTicks(1), labels=axTicks(1))
}
segments(ti.l, y, ti.r, y, col=col.hor, lty=lty,
lwd=lwd)
}
if (do.points)
points(xval, Fn.kn, pch=pch, col=col.points, cex=cex.points)
if (verticals)
segments(xval, y[-n], xval, y[-1L], col=col.vert, lty=lty,
lwd=lwd)
invisible(list(t=ti, y=y))
}
plot_stepfun(stepfun(x=dates, y=c(0, 1, 2)), do.points=FALSE) ## works!
plot_stepfun(stepfun(x=dates, y=c(0, 1, 2)), do.points=FALSE, xlim=lims) ## works!
plot_stepfun(stepfun(x=dates, y=c(0, 1, 2)), do.points=FALSE, xlim=dates) ## works!
plot_stepfun(stepfun(x=dates, y=c(0, 1, 2)), do.points=FALSE, xlim=limits) ## works!
Data:
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"))