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