2

I need to convert time intervals in the format %H:%M:%S (class = factor) to class = difftime. I am currently using as.difftime() to do this, but it returns NA when the hour value is > 23.

TimeElapsed_raw = as.factor(c("03:59:59", "21:00:00", "01:03:46", "44:00:00", "24:59:59"))
TimeElapsed = as.difftime(as.character(TimeElapsed_raw), format = "%H:%M:%S")
TimeElapsed

Time differences in hours
[1]  3.999722 21.000000  1.062778        NA        NA

I have the same problem whether or not I include the format statement in as.difftime():

as.difftime("65:01:17")
Time difference of NA secs

But this works:

as.difftime(65.1, units = "hours")
Time difference of 65.1 hours

I've also tried using the lubridate as.duration() function, but the values it calculates seem nonsensical.

as.duration(TimeElapsed_raw)
[1] "2s" "3s" "1s" "5s" "4s"

Any help would be appreciated!

pradlee
  • 23
  • 3
  • 2
    That only works with a numeric. Because i'm reading my data in from a csv with ':' in it, I can only format it as a factor or character. Trying to use as.numeric() on the values just gives me 'NA's. – pradlee May 12 '17 at 19:15

1 Answers1

1

You could first change the format of your data to xH xM xS which is understood by the duration function in lubridate:

x=gsub("(^\\d{2}):(\\d{2}):(\\d{2})$","\\1H \\2M \\3S",as.character(TimeElapsed_raw))
[1] "03H 59M 59S" "21H 00M 00S" "01H 03M 46S" "44H 00M 00S" "24H 59M 59S"

And then apply duration:

duration(x)
[1] "14399s (~4 hours)"     "75661s (~21.02 hours)" "3826s (~1.06 hours)"  
[4] "158461s (~1.83 days)"  "89999s (~1.04 days)"  

Otherwise, using as.difftime, you could first split your data into hours, minutes and seconds and feed each one seperately to as.difftime:

v=lapply(strsplit(TimeElapsed_raw,":"),function(x) {as.difftime(as.numeric(x[1]),units="hours")+as.difftime(as.numeric(x[2]),units="mins")+as.difftime(as.numeric(x[3]),units="secs")})

[[1]]
Time difference of 14399 secs

[[2]]
Time difference of 75600 secs

[[3]]
Time difference of 3826 secs

[[4]]
Time difference of 158400 secs

[[5]]
Time difference of 89999 secs

If you want to convert the list to a vector, make sure to reconvert it to difftime afterwards as unlist loses the class.

v=as.difftime(unlist(v),unit="secs")
Lamia
  • 3,845
  • 1
  • 12
  • 19
  • What if I want to output the durations in hours, not secs? If I just change the unit to "hours" in the unlist() step, the values themselves stay the same. E.g. "Time difference of 14399 secs" in the lapply() step is saved as "Time difference of 14399 hours". – pradlee May 12 '17 at 21:02
  • After the `unlist()`, `v` is considered as `numeric`, so when you apply `as.difftime()`, you need to specify that your input is in seconds. If afterwards, you want to change the unit of a `difftime` object to hours, just do `units(v)="hours"`. – Lamia May 12 '17 at 21:12