简体   繁体   中英

New Variable Based on Previous Observation

I have sleep data that includes one field for the time my son went to bed and another field for what time he woke up. I want to create a new variable that calculates total time spent asleep. In other words I need the difference between wake time for each day and bed time ON THE PREVIOUS DAY.

library(lubridate)

day <- mdy("8/27/19","8/28/19","8/29/19")
wake <- hms("7:35:00","7:45:00","7:30:00")
bed <- hms("19:45:00","20:15:00","20:00:00")
toy_data <- tibble(day, wake, bed)

I tried doing this with a loop:

toy_data$sleeptime <- NA

for(i in 1:nrow(toy_data)){
  toy_data$sleeptime[i] <- as.duration(toy_data$bed[i-1] - toy_data$wake[i])
}

but get an error:

replacement has length zero
library(dplyr)
toy_data %>%
  mutate(sleep_time = as.duration(wake) - lag(as.duration(bed)) + dhours(24))

# A tibble: 3 x 4
  day        wake         bed          sleep_time           
  <date>     <S4: Period> <S4: Period> <S4: Duration>       
1 2019-08-27 7H 35M 0S    19H 45M 0S   NA                   
2 2019-08-28 7H 45M 0S    20H 15M 0S   43200s (~12 hours)   
3 2019-08-29 7H 30M 0S    20H 0M 0S    40500s (~11.25 hours)

I wasn't having luck getting the lag of the original columns in S4: Period form, but it worked when I did the calculation between two durations.

ind = match(toy_data$day - 1, toy_data$day)
as.numeric(ymd_hms(paste(toy_data$day, toy_data$wake)) - 
               ymd_hms(paste(toy_data$day[ind], toy_data$bed[ind])))
#[1]    NA 12.00 11.25
#Warning message:
# 1 failed to parse. 

One option that might make things more simple would be to pass in strings rather than mdy and hms objects, which makes it easy to turn each column into a full date object that is easily manipulated:

library(tidyverse)
library(lubridate)

day <- c("8/27/19","8/28/19","8/29/19")
wake <- c("7:35:00","7:45:00","7:30:00")
bed <- c("19:45:00","20:15:00","20:00:00")
toy_data <- tibble(day, wake, bed)

toy_data %>% 
  mutate(
    wake = mdy_hms(str_c(day, wake, sep = " ")),
    bed = mdy_hms(str_c(day, bed, sep = " ")),
    sleep = lead(wake) - bed
  )

# A tibble: 3 x 4
  day     wake                bed                 sleep      
  <chr>   <dttm>              <dttm>              <drtn>     
1 8/27/19 2019-08-27 07:35:00 2019-08-27 19:45:00 12.00 hours
2 8/28/19 2019-08-28 07:45:00 2019-08-28 20:15:00 11.25 hours
3 8/29/19 2019-08-29 07:30:00 2019-08-29 20:00:00    NA hours

Then you can use lead to access the wake time from the next day, or make the small alteration to lag if you want the sleep time to show up on the following day.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM