Assign diel period using for loop and ifelse

I'm trying to assign a diel period to observations based on the time and the month the observation was made.
I have separate data frames, one containing the month and time of the observation and the other containing the starting and ending times for each diel period for each month.

I've written many iterations of code and the closest I have gotten assigns the diel period for the LAST month for all the data (in this case month 12), regardless of the month when the observation was made. Obviously this results in incorrect diel assignment for the other months!

I suspect there is an issue with the indexing but haven't been able to figure it out. Any insight would be very much appreciated.

I have attached a google drive link for the .csv containing my diel period classifications:
https://drive.google.com/file/d/1o0BOnAQnYsx0PJZ5vvWaTWX0IZndrS7p/view?usp=sharing

library(tidyverse)
library(hms)

#csv containing diel period classifications
diel <- read_csv("DielPeriod.csv")

#generate data 
month <- sort(as.numeric(rep(c(1:12), times = 3)), decreasing = F)
time <- as_hms(rep(c("08:00:00", "13:00:00", "19:00:00"), times = 12))
data <-data.frame(month, time)

#assign diel period based on month and time
for (i in 1:nrow(data)){
  t<-data$month[i]
  data$dielperiod <- ifelse(data$time > diel[t, "CT_Start"] & data$time <= diel[t,"Morning_End"], "morning",
                             ifelse(data$time > diel[t, "Morning_End"] & data$time <= diel[t,"Evening_Start"], "midday",
                                    ifelse(data$time > diel[t, "Evening_Start"] & data$time <= diel[t,"CT_End"], "evening",
                                           NA)))
}

Is this close to what you want? I used a case_when instead of nested ifelse.

library(hms)
library(dplyr)
#> 
#> Attaching package: 'dplyr'
#> The following objects are masked from 'package:stats':
#> 
#>     filter, lag
#> The following objects are masked from 'package:base':
#> 
#>     intersect, setdiff, setequal, union
month <- sort(as.numeric(rep(c(1:12), times = 3)), decreasing = F)
time <- as_hms(rep(c("08:00:00", "13:00:00", "19:00:00"), times = 12))
data <-data.frame(month, time)
Diel <- read.csv("~/R/Play/DielPeriod2.csv")
Diel <- Diel %>% mutate(across(.cols = CT_Start:CT_End, .fns =  as_hms))
data <- inner_join(data,Diel, by = c(month = "Month"))
data <- data %>% mutate( DielPeriod = case_when(
  time > CT_Start & time <= Morning_End ~ "Morning",
  time > Morning_End & time < Evening_Start ~ "midday",
  time > Evening_Start & time <= CT_End ~ "evening",
  TRUE ~ NA_character_
))
head(data)
#>   month     time CT_Start Morning_End Evening_Start   CT_End DielPeriod
#> 1     1 08:00:00 07:00:00    10:00:00      14:45:00 17:45:00    Morning
#> 2     1 13:00:00 07:00:00    10:00:00      14:45:00 17:45:00     midday
#> 3     1 19:00:00 07:00:00    10:00:00      14:45:00 17:45:00       <NA>
#> 4     2 08:00:00 06:36:00    09:36:00      15:18:00 18:18:00    Morning
#> 5     2 13:00:00 06:36:00    09:36:00      15:18:00 18:18:00     midday
#> 6     2 19:00:00 06:36:00    09:36:00      15:18:00 18:18:00       <NA>

Created on 2021-05-19 by the reprex package (v0.3.0)

1 Like

I should have mentioned I edited the csv file to get as_hms to work with it. I am not familiar with the hms package, so that may not be necessary.

This does accomplish my goal, thank you! However for the sake of keeping my data frames smaller and also to learn more about how indexing works, I would like to know how to accomplish this without joining the data frames as well.

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.

If you have a query related to it or one of the replies, start a new topic and refer back with a link.