Search code examples
rtimedifference

Find difference between time in R


I would like to calculate time difference in R of "A" and "B". The data that I have is the hour/minute/am-pm of individuals when they go to sleep("A") and at what time they wake up("B"): (df is called time)

    Hour(A) Min(A) AMPM(A) Hour(B) Min(B) AMPM(B)
    1       30     AM      7       30     AM
    4       00     AM      9       00     AM
    11      30     PM      6       30     AM 

I have been doing some research and what I found is that I could create the time as a character and then change it as a time formate.

First, I used the unite() function (tidyverse) to join the hour(A) and min(A). Then, I created another column with a "fake" date (if it was pm: "2019-04-13" & am "2019-04-14"). Then, I used again the function unite() to join the date and the time and with the function strptime() I change the class to time.

For hour(B), min(B) and AMPM(B), I also used the function unite and join the three columns. Then I applied the function strptime() to change the class to a time.

Finally, I am using the function difftime() to find the difference between A and B, but I can't understand why I am getting unusual results.


time <- time %>% mutate(Date = ifelse(AMPM(A) == "  AM", "2019-04-14", "2019-04-13"))

time$Date <- as.Date(time$Date)

#Using unite to join Hour(A) with Mins(A) and Hour(B) with Mins(B)
time <- time %>% unite(Sleeptime,HourA,MinsA, sep = ":") %>% unite(Wakeuptime, HourB,MinsB, sep = ":") 

#Adding the seconds 
time$Sleeptime <- paste0(time$Sleeptime,":00")

#Using unite to join Hours(B)Mins(B) with AMPM(B)
time <- time %>% unite(Wakeuptime, Wakeuptime ,AMPMWake, sep = "" )

#Changing the class for time (B)
time$Wakeuptime2 <- strptime(x = paste0(time$Wakeuptime2, "m"), format = "%I:%M %p")

#Joining the fake date for (A) with the time(A)
time <- time %>% unite(ST, Date, Sleeptime, sep = " ")

#Changing the class for time (A)
time$ST = strptime(time$ST,format='%Y-%m-%d %H:%M:%S')

#Calculating the difference in time 
time$difference <- difftime(time$Wakeuptime2, time$ST, units = "hours")

What I need is another column with the difference in hour or minutes

    Hour(A) Min(A) AMPM(A) Hour(B) Min(B) AMPM(B) DIFF (min)
    1       30     AM      7       30     AM      300
    4       00     AM      9       00     AM      300
    11      30     PM      6       30     AM      420

Solution

  • We could use paste to assemble the fragments of time(A) and time(B), then convert as.POSIXct. From bed-times with PM we subtract 8.64e4 (one day in seconds). Now it's easy to calculate the differences within an apply.

    tmp <- sapply(list(1:3, 4:6), function(x) {
      cl <- as.POSIXct(apply(time[x], 1, paste, collapse=":"), format="%I:%M:%p")
      return(ifelse(time[tail(x, 1)] == "PM", cl - 8.64e4, cl))
      })
    time <- cbind(time, `DIFF(min)`=apply(tmp, 1, diff)/60)
    time
    #   Hour(A) Min(A) AMPM(A) Hour(B) Min(B) AMPM(B) DIFF(min)
    # 1       1     30      AM       7     30      AM       360
    # 2       4      0      AM       9      0      AM       300
    # 3      11     30      PM       6     30      AM       420
    

    Data

    time <- structure(list(`Hour(A)` = c(1L, 4L, 11L), `Min(A)` = c(30L, 
    0L, 30L), `AMPM(A)` = c("AM", "AM", "PM"), `Hour(B)` = c(7L, 
    9L, 6L), `Min(B)` = c(30L, 0L, 30L), `AMPM(B)` = c("AM", "AM", 
    "AM")), row.names = c(NA, -3L), class = "data.frame")