`by()` changed POSIXct to numeric value in R

43 views Asked by At

In R, how to prevent the by() function from changing POSIXct to numeric values automatically?


In the following example, the time object is class "POSIXct" "POSIXt". When using by() function, the output is numeric. But when doing what by() does manually, e.g. min(time[index=='a']), the output is still "POSIXct" "POSIXt", which is desired. Is there a way to prevent the by() function from changing POSIXct to numeric values automatically?

time = c("0001-03-04 05:36:00 UTC", "0001-03-04 05:50:00 UTC", "0001-03-04 06:05:00 UTC")
time = as.POSIXct(time, tz = "UTC")
index = c("a", "a", "b")

by(time, index, min) # results are numeric values.
min(time[index=='a']) # "0001-03-04 05:36:00 UTC"
1

There are 1 answers

0
G. Grothendieck On BEST ANSWER

1) Return a list and then concatenate the elements of the result.

do.call("c", by(time, index, function(x) list(min(x))))
##                         a                         b 
## "0001-03-04 05:36:00 UTC" "0001-03-04 06:05:00 UTC" 

2) split/lapply would also work:

do.call("c", lapply(split(time, index), min))
##                         a                         b 
## "0001-03-04 05:36:00 UTC" "0001-03-04 06:05:00 UTC" 

3) as would tapply with simplify = FALSE:

do.call("c", tapply(time, index, min, simplify = FALSE))
##                         a                         b 
## "0001-03-04 05:36:00 UTC" "0001-03-04 06:05:00 UTC" 

4) aggregate can be used.

with(aggregate(time ~., data.frame(time, index), min), setNames(time, index))
##                         a                         b 
## "0001-03-04 05:36:00 UTC" "0001-03-04 06:05:00 UTC" 

or if names are not needed:

aggregate(time, list(index), min)$x
## [1] "0001-03-04 05:36:00 UTC" "0001-03-04 06:05:00 UTC"

or to get a data frame result:

aggregate(time ~., data.frame(time, index), min)
##   index                time
## 1     a 0001-03-04 05:36:00
## 2     b 0001-03-04 06:05:00