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.
OP brought up the issue of missing values in the comments. My initial solution fails with Error in NextMethod(.Generic) : NAs are not allowed in subscripted assignments. Following here, one fix is to check for NAs when subscripting:
Wakeup <- c("0700", NA, "0815")
Bedtime <- c("2400", "2230", "0100")
IsNA <- is.na(Wakeup) | is.na(Bedtime) # FALSE TRUE FALSE
Wakeup <- as.POSIXct(Wakeup, format='%H%M')
Bedtime <- as.POSIXct(Bedtime, format='%H%M')
# subscripting accounts for NAs now
Bedtime[Bedtime > Wakeup & ! IsNA] <- Bedtime[Bedtime > Wakeup & ! IsNA] - as.difftime(1, units='days')
Hours_slept <- as.numeric(difftime(Wakeup, Bedtime, units='hours'))
# 7.00 NA 7.25
But this also led me to another solution, which I maybe prefer in general. Calculate the difference in the automatically generated date times, and add 24 (hours) to any negative values. This seems to work with NAs without any additional fuss (it uses ifelse and avoids the subscripting with NA):
Wakeup <- c("0700", "0515", "0815")
Bedtime <- c("2400", "2230", NA)
Wakeup <- as.POSIXct(Wakeup, format='%H%M')
Bedtime <- as.POSIXct(Bedtime, format='%H%M')
Hours_slept <- as.numeric(difftime(Wakeup, Bedtime, units='hours'))
Hours_slept <- ifelse(Hours_slept < 0, Hours_slept + 24, Hours_slept)
# 7.00 6.75 NA