I have two columns stored as character data that represent 24-hour time.
Wakeup <- c("0700", "0515", "0815")
Bedtime <- c("2400", "2230", "0100")
I would like to subtract these times and get the desired column below (as numeric).
Hours_slept <- c(7, 6.75, 7.25)
I would like to use the tidyverse.
CodePudding user response:
There's a few interesting things to think through here, such as how to convert to a time object (if that's what you're aiming for) and how to work out time distance without a date (we can tell that 2230 is day before wakeup and 0100 is same day, but R doesn't).
If you want to stick to very tidyversey ways of doing things, then you can make it a tibble and mutate
using lubridate
functions:
library(tidyverse)
library(lubridate)
Wakeup <- c("0700", "0515", "0815")
Bedtime <- c("2400", "2230", "0100")
tibble(Bedtime, Wakeup) %>%
mutate(
# First change makes each a time, formatting time string by inserting space
across(.fns = ~ str_replace(.x, "(?=\\d{2}$)", " ") %>% hm()),
# Then time difference
time_diff = Wakeup - Bedtime,
# Some are negative - a quick fix may be just to add 24h
time_diff = if_else(time_diff < 0, hours(24) time_diff, time_diff),
# Then convert to decimal number of hours
time_diff = as.numeric(time_diff) / (60 * 60)
)
#> # A tibble: 3 × 3
#> Bedtime Wakeup time_diff
#> <Period> <Period> <dbl>
#> 1 24H 0M 0S 7H 0M 0S 7
#> 2 22H 30M 0S 5H 15M 0S 6.75
#> 3 1H 0M 0S 8H 15M 0S 7.25
Created on 2022-05-26 by the reprex package (v2.0.1)
CodePudding user response:
Here's a base R implementation. Like Andy mentioned, there is an assumption that the Bedtime
must be before Wakeup
, and by no more than a day:
Wakeup <- c("0700", "0515", "0815")
Bedtime <- c("2400", "2230", "0100")
Wakeup <- as.POSIXct(Wakeup, format='%H%M')
Bedtime <- as.POSIXct(Bedtime, format='%H%M')
Bedtime[Bedtime > Wakeup] <- Bedtime[Bedtime > Wakeup] - as.difftime(1, units='days')
Hours_slept <- as.numeric(difftime(Wakeup, Bedtime, units='hours'))
# [1] 7.00 6.75 7.25
The input hours are converted into datetimes, (which by default will take the current date). Subtract one day from any times where the bed time is greater than the corresponding wakeup. Then subtract the datetimes with difftime
and get the data in numeric hours.