Returning a Vector of Class Posixct with Vapply

Returning a vector of class POSIXct with vapply

What about do.call?

L <- list(as.POSIXct("2012-12-12 12:12:12"), as.POSIXct("2012-12-12 12:12:12"))
do.call(c, L) # Execute function c on a list L of arguments.
[1] "2012-12-12 12:12:12 CET" "2012-12-12 12:12:12 CET"

How to make vapply return a date vector?

The problem is that apply family functions drop Date class. Here is one way to do it:

do.call("c", lapply(3:7, f1))

You can also add class(result) <- "Date" after evaluating vapply.

Full version of class(result) <- "Date":

result <- vapply(3:7, f1, numeric(1))
class(result) <- "Date"
result
# "2000-03-01" "2000-04-01" "2000-05-01" "2000-06-01" "2000-07-01"

Passing POSIXct object to function returns numeric vector

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") )

Why is POSIXct converted to numeric when converting list to vector

You can reproduce more easily like this:

x <- list(as.POSIXct("2016-11-02"), as.POSIXct("2016-11-03"))
unlist(x)
#[1] 1478041200 1478127600

unlist combines the values inside the list. The internal representation of POSIXct variables are numeric values. They only are a POSIXct variable due to attributes, most importantly the class attribute. A list can hold all kinds of objects. The documentation says:

Where possible the list elements are coerced to a common mode during
the unlisting, and so the result often ends up as a character vector.
Vectors will be coerced to the highest type of the components in the
hierarchy NULL < raw < logical < integer < double < complex <
character < list < expression: pairlists are treated as lists.

Note that it says "common mode", not common class. Since a class could be anything and could enforce any kind of underlying structure (e.g., it might not even be possible to combine two objects of the same class in a meaningful way), unlist just strips all attributes (except for a list where all elements are factors). It would be possible to handle POSIXct values like factor values, but that's not the case (and might have performance implications).

You can't avoid this, but fix it easily:

y <- unlist(x)
attributes(y) <- attributes(x[[1]])
y
#[1] "2016-11-02 CET" "2016-11-03 CET"

Obviously this assumes that all list elements have the same timezone attribute.

Understanding why sapply in R returns vector of longer length

To specifically answer the reason for 688 is that you are assigning values by un-ordered indexes from values of calc_size to the empty vector, likelihoods. Specifically, calc_sizes comprises of 87 integer values. Notice the smallest term is 1 and largest term is 688.

calc_sizes

[1] 1 40 2 3 180 4 19 21 10 49 6 18 5 11 81 23 186 189 8
[20] 41 27 20 7 12 68 9 25 16 131 15 51 26 22 17 648 24 30 32
[39] 28 36 53 96 47 14 548 109 38 31 99 106 34 39 607 100 233 42 66
[58] 129 33 170 102 70 13 46 63 79 97 447 460 688 346 130 44 69 620 113
[77] 92 256 153 78 462 325 61 64 54 76 86

However, your intended sapply also contains 87:

sapply(calc_sizes, nb.likelihood) 

[1] -1.098612 -11.788381 -2.602690 -3.413620 -30.541489 -4.001407
[7] -8.187640 -8.575276 -6.146104 -13.154588 -4.881330 -7.987619
[13] -4.475865 -6.410490 -17.680645 -8.948901 -31.297439 -31.674821
[19] -5.565697 -11.943435 -9.663029 -8.383385 -5.240275 -6.661805
[25] -15.886160 -5.865802 -9.310881 -7.572668 -24.292698 -7.356445
[31] -13.450466 -9.488087 -8.763676 -7.782825 -87.586858 -9.131222
[37] -10.175841 -10.509013 -9.835872 -11.158148 -13.744013 -19.702968
[43] -12.856183 -7.133302 -75.557026 -21.425116 -11.475373 -10.343221
[49] -20.102594 -21.029806 -10.836219 -11.632377 -82.659672 -20.235490
[55] -37.171587 -12.097586 -15.605646 -24.034010 -10.673316 -29.277798
[61] -20.500835 -16.165367 -6.902190 -12.705964 -15.182243 -17.407459
[67] -19.836336 -63.355209 -64.929415 -92.388061 -51.074698 -24.163398
[73] -12.403344 -16.025922 -84.222650 -21.950431 -19.167825 -40.021951
[79] -27.117199 -17.270506 -65.171492 -48.507264 -14.898089 -15.323743
[85] -13.889967 -16.995849 -18.359679

So in your assignment you are assigning by indexed positions the values of sapply, spread out elementwise.

likelihoods[calc_sizes] <- sapply(calc_sizes, nb.likelihood) 

likelihoods

[1] -1.098612 -2.602690 -3.413620 -4.001407 -4.475865 -4.881330
[7] -5.240275 -5.565697 -5.865802 -6.146104 -6.410490 -6.661805
[13] -6.902190 -7.133302 -7.356445 -7.572668 -7.782825 -7.987619
[19] -8.187640 -8.383385 -8.575276 -8.763676 -8.948901 -9.131222
[25] -9.310881 -9.488087 -9.663029 -9.835872 NA -10.175841
[31] -10.343221 -10.509013 -10.673316 -10.836219 NA -11.158148
[37] NA -11.475373 -11.632377 -11.788381 -11.943435 -12.097586
[43] NA -12.403344 NA -12.705964 -12.856183 NA
[49] -13.154588 NA -13.450466 NA -13.744013 -13.889967
[55] NA NA NA NA NA NA
[61] -14.898089 NA -15.182243 -15.323743 NA -15.605646
[67] NA -15.886160 -16.025922 -16.165367 NA NA
[73] NA NA NA -16.995849 NA -17.270506
[79] -17.407459 NA -17.680645 NA NA NA
[85] NA -18.359679 NA NA NA NA
[91] NA -19.167825 NA NA NA -19.702968
[97] -19.836336 NA -20.102594 -20.235490 NA -20.500835
[103] NA NA NA -21.029806 NA NA
[109] -21.425116 NA NA NA -21.950431 NA
[115] NA NA NA NA NA NA
[121] NA NA NA NA NA NA
[127] NA NA -24.034010 -24.163398 -24.292698 NA
[133] NA NA NA NA NA NA
[139] NA NA NA NA NA NA
[145] NA NA NA NA NA NA
[151] NA NA -27.117199 NA NA NA
[157] NA NA NA NA NA NA
[163] NA NA NA NA NA NA
[169] NA -29.277798 NA NA NA NA
[175] NA NA NA NA NA -30.541489
[181] NA NA NA NA NA -31.297439
[187] NA NA -31.674821 NA NA NA
[193] NA NA NA NA NA NA
[199] NA NA NA NA NA NA
[205] NA NA NA NA NA NA
[211] NA NA NA NA NA NA
[217] NA NA NA NA NA NA
[223] NA NA NA NA NA NA
[229] NA NA NA NA -37.171587 NA
[235] NA NA NA NA NA NA
[241] NA NA NA NA NA NA
[247] NA NA NA NA NA NA
[253] NA NA NA -40.021951 NA NA
[259] NA NA NA NA NA NA
[265] NA NA NA NA NA NA
[271] NA NA NA NA NA NA
[277] NA NA NA NA NA NA
[283] NA NA NA NA NA NA
[289] NA NA NA NA NA NA
[295] NA NA NA NA NA NA
[301] NA NA NA NA NA NA
[307] NA NA NA NA NA NA
[313] NA NA NA NA NA NA
[319] NA NA NA NA NA NA
[325] -48.507264 NA NA NA NA NA
[331] NA NA NA NA NA NA
[337] NA NA NA NA NA NA
[343] NA NA NA -51.074698 NA NA
[349] NA NA NA NA NA NA
[355] NA NA NA NA NA NA
[361] NA NA NA NA NA NA
[367] NA NA NA NA NA NA
[373] NA NA NA NA NA NA
[379] NA NA NA NA NA NA
[385] NA NA NA NA NA NA
[391] NA NA NA NA NA NA
[397] NA NA NA NA NA NA
[403] NA NA NA NA NA NA
[409] NA NA NA NA NA NA
[415] NA NA NA NA NA NA
[421] NA NA NA NA NA NA
[427] NA NA NA NA NA NA
[433] NA NA NA NA NA NA
[439] NA NA NA NA NA NA
[445] NA NA -63.355209 NA NA NA
[451] NA NA NA NA NA NA
[457] NA NA NA -64.929415 NA -65.171492
[463] NA NA NA NA NA NA
[469] NA NA NA NA NA NA
[475] NA NA NA NA NA NA
[481] NA NA NA NA NA NA
[487] NA NA NA NA NA NA
[493] NA NA NA NA NA NA
[499] NA NA NA NA NA NA
[505] NA NA NA NA NA NA
[511] NA NA NA NA NA NA
[517] NA NA NA NA NA NA
[523] NA NA NA NA NA NA
[529] NA NA NA NA NA NA
[535] NA NA NA NA NA NA
[541] NA NA NA NA NA NA
[547] NA -75.557026 NA NA NA NA
[553] NA NA NA NA NA NA
[559] NA NA NA NA NA NA
[565] NA NA NA NA NA NA
[571] NA NA NA NA NA NA
[577] NA NA NA NA NA NA
[583] NA NA NA NA NA NA
[589] NA NA NA NA NA NA
[595] NA NA NA NA NA NA
[601] NA NA NA NA NA NA
[607] -82.659672 NA NA NA NA NA
[613] NA NA NA NA NA NA
[619] NA -84.222650 NA NA NA NA
[625] NA NA NA NA NA NA
[631] NA NA NA NA NA NA
[637] NA NA NA NA NA NA
[643] NA NA NA NA NA -87.586858
[649] NA NA NA NA NA NA
[655] NA NA NA NA NA NA
[661] NA NA NA NA NA NA
[667] NA NA NA NA NA NA
[673] NA NA NA NA NA NA
[679] NA NA NA NA NA NA
[685] NA NA NA -92.388061

Notice the 70th term of calc_size is 688 and the 70th term of sapply(calc_sizes, nb.likelihood) is -92.38806 (the last numeric value above).

calc_sizes[70]
# [1] 688

sapply(calc_sizes, nb.likelihood)[70]
# [1] -92.3880

To resolve, run along the length of calc_sizes to assign by 1:87. Also, consider initializing likelihoods with a length instead of growing the object after c().

likelihoods <- vector(mode="numeric", length=length(calc_sizes))

likelihoods[seq_along(calc_sizes)] <- sapply(calc_sizes, nb.likelihood)
# likelihoods[1:length(calc_sizes)] <- sapply(calc_sizes, nb.likelihood)

Nevertheless, since apply family functions return an object, simple assign directly to the sapply call without initializing anything.

likelihoods <- sapply(calc_sizes, nb.likelihood) 

likelihoods
[1] -1.098612 -11.788381 -2.602690 -3.413620 -30.541489 -4.001407
[7] -8.187640 -8.575276 -6.146104 -13.154588 -4.881330 -7.987619
[13] -4.475865 -6.410490 -17.680645 -8.948901 -31.297439 -31.674821
[19] -5.565697 -11.943435 -9.663029 -8.383385 -5.240275 -6.661805
[25] -15.886160 -5.865802 -9.310881 -7.572668 -24.292698 -7.356445
[31] -13.450466 -9.488087 -8.763676 -7.782825 -87.586858 -9.131222
[37] -10.175841 -10.509013 -9.835872 -11.158148 -13.744013 -19.702968
[43] -12.856183 -7.133302 -75.557026 -21.425116 -11.475373 -10.343221
[49] -20.102594 -21.029806 -10.836219 -11.632377 -82.659672 -20.235490
[55] -37.171587 -12.097586 -15.605646 -24.034010 -10.673316 -29.277798
[61] -20.500835 -16.165367 -6.902190 -12.705964 -15.182243 -17.407459
[67] -19.836336 -63.355209 -64.929415 -92.388061 -51.074698 -24.163398
[73] -12.403344 -16.025922 -84.222650 -21.950431 -19.167825 -40.021951
[79] -27.117199 -17.270506 -65.171492 -48.507264 -14.898089 -15.323743
[85] -13.889967 -16.995849 -18.359679

Online Demo

ifelse() stripping POSIXct attribute from vector of timestamps?

If you look at the way ifelse is written, it has a section of code that looks like this:

ans <- test
ok <- !(nas <- is.na(test))
if (any(test[ok]))
ans[test & ok] <- rep(yes, length.out = length(ans))[test & ok]

Note that the answer starts off as a logical vector, the same as test. The elements that have test == TRUE then get assigned to the value of yes.

The issue here then is with what happens with assignment of an element or elements of a logical vector to be a date of class POSIX.ct. You can see what happens if you do this:

x <- c(TRUE, FALSE)
class(x)
# logical
x[1] <- Sys.time()
class(x)
# numeric

You could get around this by writing:

timestamp <- timestamp + 30
timestamp[is.na(timestamp)] <- fixedDate

You could also do this:

fixedDate = as.POSIXct(strptime("2000-01-01 12:00:00.000000", formatString))
unlist(ifelse(is.na(timestamp), as.list(fixedDate), as.list(timestamp+30)))

This takes advantage of the way the replacement operator [<- handles a list on the right hand side.

You can also just re-add the class attribute like this:

x <- ifelse(is.na(timestamp), fixedDate, timestamp+30)
class(x) <- c("POSIXct", "POSIXt")

or if you were desperate to do it in one line like this:

`class<-`(ifelse(is.na(timestamp), fixedDate, timestamp+30), c("POSIXct", "POSIXt"))

or by copying the attributes of fixedDate:

x <- ifelse(is.na(timestamp), fixedDate, timestamp+30)
attributes(x) <- attributes(fixedDate)

This last version has the advantage of copying the tzone attribute as well.

As of dplyr 0.5.0, you can also use dplyr::if_else which preserves class in the output and also enforces the same class for the true and false arguments.



Related Topics



Leave a reply



Submit