I was wondering how I could plot more tick marks when plotting time on the x-axis.
Basically, a time equivalent to pretty. Pretty obviously doesn't work so well with times, as it uses factors of 1,2,5 and 10. For time one probably wants e.g. hours, half hours, ...
plot(as.POSIXct(x,origin="1960-01-01"),y,type="l",xlab="Time")
gives really too few and widely spaced tickmarks.
zoox<-zoo(y,as.POSIXct(stats$Time,origin="1960-01-01"))
plot(zoox)
gives the same.
Thanks
EDIT:
Just to clarify (so far answers don't address my issue): What I am looking for is a function like pretty for dates, e.g. a function, that takes a start date, an end date, a number of ticks, and outputs the location of the ticks. That is, I am well aware it is possible to plot hours, to plot minutes, and what else, but pretty automates the tick distance for numbers, and a resulting function for dates should decide by itself whether to use days, hours, minutes, second, milliseconds, microseconds, 30 minutes, 500 micros, 5 seconds, etc. intervals. That is what pretty does for numbers, anyway.
EDIT2:
This is the function I currently use to decide the format for the time axis (note that this doesn't work for dates):
mydiff <- end-start
if(mydiff>1800) {
axis.POSIXct(1,xrange,format="%H:%M")
} else if(mydiff>30) {
axis.POSIXct(1,xrange,format="%H:%M:%S")
} else if(mydiff>0.5) {
axis.POSIXct(1,xrange,format="%H:%M:%OS3")
} else
axis.POSIXct(1,xrange,format="%H:%M:%OS6")
}
I don't have a function that increase tick marks, so I use the default number of tick marks
axis.POSIXct()
already works quite hard to guess suitable pretty values for the axis, so I would start by hacking that. At the moment, it relies internally on using pretty()
applied to the some function of the datetimes. It uses the defaults for pretty()
so you could hack the function to add an n
or min.n
argument which would increase the number of pretty marks selected.
Copy axis.POSIXct()
to your own function/file (give it a new name). Add a n
or min.n
argument to the definition, probably with larger values as defaults than those used by the pretty()
function. And pass that to each of the pretty()
calls that is made.
Try it out. If it works reasonably well, then you can do fixInNamespace(axis.POSIXct)
to make the same changes to the actual function so it gets used on all plots for which it is called.
P.S. Here is a possible hack
function (side, x, at, format, labels = TRUE, n = 5, ...) {
mat <- missing(at) || is.null(at)
if (!mat)
x <- as.POSIXct(at)
else x <- as.POSIXct(x)
range <- par("usr")[if (side%%2)
1L:2L
else 3L:4L]
d <- range[2L] - range[1L]
z <- c(range, x[is.finite(x)])
attr(z, "tzone") <- attr(x, "tzone")
if (d < 1.1 ) {
sc <- 0.001
if (missing(format))
format <- "%H:%M:%OS6"
}
else if (d < 1.1 * 30) {
sc <- 1
if (missing(format))
format <- "%H:%M:%OS3"
}
else if (d < 1.1 * 60) {
sc <- 1
if (missing(format))
format <- "%H:%M:%S"
}
else if (d < 1.1 * 30 * 60) {
sc <- 60
if (missing(format))
format <- "%H:%M:%S"
}
else if (d < 1.1 * 60 * 60) {
sc <- 60
if (missing(format))
format <- "%H:%M"
}
else if (d < 1.3 * 60 * 60 * 24) {
sc <- 60 * 60
if (missing(format))
format <- "%H:%M"
}
else if (d < 2 * 60 * 60 * 24) {
sc <- 60 * 60
if (missing(format))
format <- "%a %H:%M"
}
else if (d < 7 * 60 * 60 * 24) {
sc <- 60 * 60 * 24
if (missing(format))
format <- "%a"
}
else {
sc <- 60 * 60 * 24
}
if (d < 60 * 60 * 24 * 50) {
zz <- pretty(z/sc,n=n)
z <- zz * sc
z <- .POSIXct(z, attr(x, "tzone"))
if (sc == 60 * 60 * 24)
z <- as.POSIXct(round(z, "days"))
if (missing(format))
format <- "%b %d"
}
else if (d < 1.1 * 60 * 60 * 24 * 365) {
z <- .POSIXct(z, attr(x, "tzone"))
zz <- as.POSIXlt(z)
zz$mday <- zz$wday <- zz$yday <- 1
zz$isdst <- -1
zz$hour <- zz$min <- zz$sec <- 0
zz$mon <- pretty(zz$mon,n=n)
m <- length(zz$mon)
M <- 2 * m
m <- rep.int(zz$year[1L], m)
zz$year <- c(m, m + 1)
zz <- lapply(zz, function(x) rep(x, length.out = M))
zz <- .POSIXlt(zz, attr(x, "tzone"))
z <- as.POSIXct(zz)
if (missing(format))
format <- "%b"
}
else {
z <- .POSIXct(z, attr(x, "tzone"))
zz <- as.POSIXlt(z)
zz$mday <- zz$wday <- zz$yday <- 1
zz$isdst <- -1
zz$mon <- zz$hour <- zz$min <- zz$sec <- 0
zz$year <- pretty(zz$year,n=n)
M <- length(zz$year)
zz <- lapply(zz, function(x) rep(x, length.out = M))
z <- as.POSIXct(.POSIXlt(zz))
if (missing(format))
format <- "%Y"
}
if (!mat)
z <- x[is.finite(x)]
keep <- z >= range[1L] & z <= range[2L]
z <- z[keep]
if (!is.logical(labels))
labels <- labels[keep]
else if (identical(labels, TRUE))
labels <- format(z, format = format)
else if (identical(labels, FALSE))
labels <- rep("", length(z))
axis(side, at = z, labels = labels, ...)
}
Differences to the original function can be seen here
I tend to use function axis.POSIXct
and/or function cut.POSIXt
. Let's say your vector of date is time
and your vector of value associated x
:
plot(time,x,xaxt="n")
axis.POSIXct(side=1,at=seq(min(time),max(time),by="week"),format="%d-%m") #For instance
And, going further, with cut.POSIXt
:
plot(time,x,xaxt="n")
axis.POSIXct(side=1,at=cut(time, breaks="week"),format="%d-%m")
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With