Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Extraction of POSIXlt component runs fine in R 3.4.4, but errors in R 3.5.0. Why?

1) R version 3.4.4 (2018-03-15)

my.timedate <- as.POSIXlt('2016-01-01 16:00:00')  
# print(attributes(my.timedate))  
print(my.timedate[['hour']])  

[1] 16

2) R version 3.5.0 (2018-04-23)

my.timedate <- as.POSIXlt('2016-01-01 16:00:00')  
# print(attributes(my.timedate))  
print(my.timedate[['hour']]) 

Error in FUN(X[[i]], ...) : subscript out of bounds

like image 872
George Rwaga Avatar asked Jun 16 '18 20:06

George Rwaga


3 Answers

I think that is a known change in R 3.5.0 where the list elements of a POSIXlt need to be unpackaged explicitly. Using R 3.5.0:

edd@rob:~$ docker run --rm -ti r-base:3.5.0 \
               R -q -e 'print(unclass(as.POSIXlt("2016-01-01 16:00:00")[["hour"]])'
> print(unclass(as.POSIXlt("2016-01-01 16:00:00"))[["hour"]])
[1] 16
> 
> 
edd@rob:~$ 

whereas with R 3.4.* one does not need the unclass() as you showed:

edd@rob:~$ docker run --rm -ti r-base:3.4.3 \
               R -q -e 'print(as.POSIXlt("2016-01-01 16:00:00")[["hour"]])'
> print(as.POSIXlt("2016-01-01 16:00:00")[["hour"]])
[1] 16
> 
> 
edd@rob:~$ 

I don't find a corresponding NEWS file entry though so not entirely sure if it is on purpose...

Edit: As others have noted, the corresponding NEWS entry is the somewhat opaque

* Single components of "POSIXlt" objects can now be extracted and
  replaced via [ indexing with 2 indices.
like image 167
Dirk Eddelbuettel Avatar answered Sep 19 '22 12:09

Dirk Eddelbuettel


From ?POSIXlt:

As from R 3.5.0, one can extract and replace single components via [ indexing with two indices (see the examples).

The example is a little opaque, but shows the idea:

leapS[1 : 5, "year"]

If you look at the source, though, you can see what's happening:

`[.POSIXlt`
#> function (x, i, j, drop = TRUE) 
#> {
#>     if (missing(j)) {
#>         .POSIXlt(lapply(X = unclass(x), FUN = "[", i, drop = drop), 
#>             attr(x, "tzone"), oldClass(x))
#>     }
#>     else {
#>         unclass(x)[[j]][i]
#>     }
#> }
#> <bytecode: 0x7fbdb4d24f60>
#> <environment: namespace:base>

It is using i to subset unclass(x), where x is the POSIXlt object. So with R 3.5.0, you use [ and preface the part of the datetime you want with the index of the datetime in the vector:

my.timedate <- as.POSIXlt('2016-01-01 16:00:00')

my.timedate[1, 'hour']
#> [1] 16

as.POSIXlt(seq(my.timedate, by = 'hour', length.out = 10))[2:5, 'hour']
#> [1] 17 18 19 20

Note that $ subsetting still works as usual:

my.timedate$hour
#> [1] 16
like image 33
alistaire Avatar answered Sep 19 '22 12:09

alistaire


See ?DateTimeClasses (same as ?as.POSIXlt):

As from R 3.5.0, one can extract and replace single components via [ indexing with two indices

See also similar description in R NEWS CHANGES IN R 3.5.0.

Thus:

my.timedate[1, "hour"]
# [1] 16

# or leave the i index empty to select a component
# from all date-times in a vector 
as.POSIXlt(c('2016-01-01 16:00:00', '2016-01-01 17:00:00'))[ , "hour"]
# [1] 16 17

See also Examples in the help text.

like image 44
Henrik Avatar answered Sep 22 '22 12:09

Henrik