I'm trying to do some manipulation on the POSIXct
vector, but when I pass it to a function, the vector changes into a numeric
vector, instead of retaining POSIXct
class, even when the function itself only returns the object:
# Sample dates from vector and it's class.
> dates <- as.POSIXct(c("2012-02-01 12:32:00", "2012-10-24 17:25:56", "2008-09-26 17:13:31", "2011-08-23 11:11:17,", "2015-09-19 22:28:33"), tz = "America/Los_Angeles")
> dates
[1] "2012-02-01 12:32:00 PST" "2012-10-24 17:25:56 PDT" "2008-09-26 17:13:31 PDT" "2011-08-23 11:11:17 PDT" "2015-09-19 22:28:33 PDT"
> class(dates)
[1] "POSIXct" "POSIXt"
# Simple subset is retaining original class.
> qq <- dates[1:5]
> qq
[1] "2012-02-01 12:32:00 PST" "2012-10-24 17:25:56 PDT" "2008-09-26 17:13:31 PDT" "2011-08-23 11:11:17 PDT" "2015-09-19 22:28:33 PDT"
> class(qq)
[1] "POSIXct" "POSIXt"
# sapply on the same subset using simple "return" function changes class to "numeric" - why? How to retain "POSIXct"?
> qq2 <- sapply(dates[1:5], function(x) x)
> qq2
[1] 1328128320 1351124756 1222474411 1314123077 1442726913
> class(qq2)
[1] "numeric"
Why it happens? How can I retain the POSIXct
class of the original vector? I know that POSIXct
is numeric
under the hood, but I want to retain the original class for readability.
We can use lapply
instead of sapply
as sapply
by default has the option simplify = TRUE
. So, if the list
elements are of the same length, it will simplify it to vector
or matrix
depending on the length of the list
elements and POSIXct
is stored as numeric
.
lst <- lapply(dates, function(x) x)
If we need to use sapply
, then an option would simplify = FALSE
lst <- sapply(dates, function(x) x, simplify=FALSE)
After applying the function, if we need as a vector output,
do.call("c", lst)
Regarding the change of timezone, it is documented in the ?DateTimeClasses
Using c on "POSIXlt" objects converts them to the current time zone, and on "POSIXct" objects drops any "tzone" attributes (even if they are all marked with the same time zone).
So, the possible option would be (as mentioned in the comments by @kmo)
.POSIXct(lst, tz = "America/Los_Angeles")
#[1] "2012-02-01 12:32:00 PST" "2012-10-24 17:25:56 PDT" "2008-09-26 17:13:31 PDT" "2011-08-23 11:11:17 PDT" "2015-09-19 22:28:33 PDT"
Or as @thelatemail mentioned in the comments
.POSIXct(sapply(dates,I), attr(dates,"tzone") )