I want to make an empty vector of POSIXct
so that I can put a POSIXct
in it:
vec <- vector(\"POSIXct\", 10)
vec
vec[1] <- \"2014-
I would go for Gregor's solution. I first went with Rich Scriven's solution but then got an error when I tried to compute the difference for a Non-NA
element later as shown in the example below
t1 <- as.POSIXct("2014-10-27 18:11:36 PDT")
t2 <- as.POSIXct("2014-11-20 18:11:36 PDT")
x <- .POSIXct(character(10))
x[1] <- t1
difftime(t2, t1)
#R Time difference of 24 days
# fails
difftime(t2, x[1])
#R Error in unclass(time1) - unclass(time2) :
#R non-numeric argument to binary operator
unclass(x[1]) # character
#R [1] "1414429896"
unclass(t1)
#R [1] 1414429896
#R attr(,"tzone")
#R [1] ""
x <- .POSIXct(rep(NA_real_, 10))
x[1] <- t1
difftime(t2, x[1]) # all good
#R Time difference of 24 days
This can even lead to strange bugs like this one which can take a while to discover
t1 <- as.POSIXct("2001-07-24 CEST")
t2 <- as.POSIXct("2002-08-29 CEST")
x <- .POSIXct(character(10))
x[1] <- t1
t2 < t1
#R [1] FALSE
t2 < x[1] # oh boy
#R [1] TRUE
# the reason (I think)
unclass(t2)
#R [1] 1030572000
#R attr(,"tzone")
#R [1] ""
unclass(x[1])
#R [1] "995925600"
"995925600" > 1030572000
#R [1] TRUE
When creating a POSIXct vector in the following way, the underlying type becomes double:
> times <- as.POSIXct(c("2015-09-18 09:01:05.984 CEST", "2015-09-18 10:01:10.984 CEST", "2015-09-18 10:21:20.584 CEST"))
> typeof(times)
[1] "double"
> values <- c(5,6,7)
Combining the above vector with an empty vector of POSIXct initialized with character as the underlying type, results in a character-POSIXct vector:
> tm1 <- c(.POSIXct(character(0)), times)
> typeof(tm1)
[1] "character"
... which cannot be plotted directly:
> ggplot() + geom_line(aes(x=tm1, y=val), data=data.frame(tm1,val))
geom_path: Each group consist of only one observation. Do you need to adjust the group aesthetic?
I therefore prefer initializing my empty POSIXct vectors with double or integer as the underlying type:
> tm2 <- c(.POSIXct(double(0)), times)
> typeof(tm2)
[1] "double"
> ggplot() + geom_line(aes(x=tm2, y=val), data=data.frame(tm2,val))
> tm3 <- c(.POSIXct(integer(0)), times)
> typeof(tm3)
[1] "double"
> ggplot() + geom_line(aes(x=tm3, y=val), data=data.frame(tm3,val))
#Same thing...
When using double, the vector is also initialized with valid dates (which might or might not be preferable):
> .POSIXct(character(10))
[1] NA NA NA NA NA NA NA NA NA NA
> .POSIXct(double(10))
[1] "1970-01-01 01:00:00 CET" "1970-01-01 01:00:00 CET" "1970-01-01 01:00:00 CET" "1970-01-01 01:00:00 CET" "1970-01-01 01:00:00 CET" "1970-01-01 01:00:00 CET"
[7] "1970-01-01 01:00:00 CET" "1970-01-01 01:00:00 CET" "1970-01-01 01:00:00 CET" "1970-01-01 01:00:00 CET"
Since there is no POSIX mode
, you cannot initialize a POSIXct
vector with vector()
alone (see ?mode
for a list of all mode types).
But we can use .POSIXct
to create the vector from a character vector.
(x <- .POSIXct(character(10))) ## the same as .POSIXct(vector("character", 10))
# [1] NA NA NA NA NA NA NA NA NA NA
class(x)
# [1] "POSIXct" "POSIXt"
Also note that you can also use .POSIXct(integer(10))
for a length 10 vector of origin date-times.
Perhaps I missed it above, but this is a truly empty POSIXct:
as.POSIXct(integer())
For example, if you want an empty data frame:
empty <- data.frame(date_time = as.POSIXct(integer()),
date = as.Date(x = integer(), origin = "1970-01-01"))
empty
[1] date_time date
<0 rows> (or 0-length row.names)
str(empty)
'data.frame': 0 obs. of 2 variables:
$ date_time: 'POSIXct' num(0)
- attr(*, "tzone")= chr ""
$ date : 'Date' num(0)
I usually initialize things to NA
:
as.POSIXct(rep(NA, 10))
works well in this case. It's explicitly doing what happens under-the-hood in @RichardScriven's answer---see the comments there for a longer discussion.
I use the following function for this. Very similar to the other solutions.
vector_datetime <- function(n = 0L) structure(rep(NA_integer_, n), class = c("POSIXct", "POSIXt"))
So you can do things like this.
> vector_datetime()
POSIXct of length 0
> vector_datetime(10)
[1] NA NA NA NA NA NA NA NA NA NA
> class(vector_datetime(10))
[1] "POSIXct" "POSIXt"
This can also be done with lubridate
.
library(lubridate)
> as_datetime(integer(0))
POSIXct of length 0