4

DATA

v1 <- c("2015-01-05 15:00:00", "2015-01-05 15:45:00", "2015-01-05 15:00:30")

OPERATIONS

v2 <- strptime(v1, '%Y-%m-%d %H:%M:%S')
str(v2)
POSIXlt[1:3], format: "2015-01-05 15:00:00" "2015-01-05 15:45:00" "2015-01-05 15:00:30"

v3 <- v2[!v2$min]  # create v3 from v2 eliminating min != 00

RESULT (successful subsetting)

str(v3)
POSIXlt[1:2], format: "2015-01-05 15:00:00" "2015-01-05 15:00:30"

Now creating v4 by coercing v2 to POSIXct (successful)

v4 <- as.POSIXct(v2, format = "%y/%m/%d  %H:%M")

str(v4)
POSIXct[1:3], format: "2015-01-05 15:00:00" "2015-01-05 15:45:00" "2015-01-05 15:00:30"

OPERATION IN QUESTION - Applying the same subsetting operation to POSIXct as to POSIXlt causes the error below

v5 <- v4[!v4$min]  # reassign v2 eliminating min != 00

RESULT (error)

  Error in v4$min : $ operator is invalid for atomic vectors

QUESTIONS:
a) Why this difference in behavior?
b) What would be an equivalent operation to use with POSIXct?
Many thanks

jpinelo
  • 1,414
  • 5
  • 16
  • 28

1 Answers1

13

You misunderstand a critical difference between POSIXlt and POSIXct:

  • POSIXlt is a 'list type' with components you can access as you do
  • POSIXct is a 'compact type' that is essentially just a number

You almost always want POSIXct for comparison and effective storage (eg in a data.frame, or to index a zoo or xts object with) and can use POSIXlt to access components. Be warned, though, that the components follow C library standards so e.g. the current years is 115 (as you always need to add 1900), weekdays start at zero etc pp.

Doing str() or unclass on these is illuminating. For historical reasons, strptime() returns a POSIXlt. I wish it would return a POSIXct.

Dirk Eddelbuettel
  • 360,940
  • 56
  • 644
  • 725
  • thank you for the clarification. I've been finding it easier to coerce to POSIXlt (via strptime()) and then to POSIXct (via as.POSIXct()). Goal is to create xts object. – jpinelo Mar 11 '15 at 20:32
  • 1
    Yes accessing part of time via conversion seems natural, eg from [lubridate](https://github.com/hadley/lubridate/blob/master/R/accessors-minute.r) `minute.default <- function(x) as.POSIXlt(x, tz = tz(x))$min` – jaimedash Mar 11 '15 at 20:41
  • 1
    @jaimedash If you know what you're doing with base R there is no need for lubridate. – Dirk Eddelbuettel Mar 11 '15 at 20:52
  • 1
    +1 I didn't mean to imply otherwise. Though my comment wasn't that clear, I intended it to show how lubridate _uses_ base R `as.POSIXlt` to access (or subset in OP's terminology) parts of `POSIXct` objects – jaimedash Mar 11 '15 at 22:57