Is there a way to isolate multiple index points in a dataset and isolate a time window around that index point in R?

Solution 1:

Here is the answer. Although long, it worked fine for gathering times 300 seconds before and 300 after the beggining of an intervention.

Let me know if you'd like further explanation or if I have misunderstood anything.

library(magrittr)
library(tidyverse)

### Sample code
id <- rep(c(1,2,3), each = 1000)
intervention <- c(rep(0,200), rep(1,10), rep(0,153), rep(0,5), rep(0,284), rep(0,20), rep(0,159), rep(0,23), rep(0,146),
                  rep(0,123), rep(1,23), rep(0,356), rep(1,8), rep(0,234), rep(1,23), rep(0,233),
                  rep(0,345), rep(1,12), rep(0,48), rep(1,15), rep(0,74), rep(1,4), rep(0,233), rep(1,82), rep(0,187))
final <- data.frame(id, intervention)
final <- final %>%
  group_by(id) %>%
  mutate(time = row_number() * 4) 

### Start of data processing to get wanted observations

# Order it by id and time
final %<>% arrange(id, time)

# Loop over the unique ids
obs_to_keep <- list()
for(i in unique(final$id)) {
  
  # Get starts of treatment
  time_zero_intervention <- final %>% 
    filter(id == i & intervention == 0) %>% 
    select(time)
  
  # Obtain all times after zero interventions, that could be intervention == 1
  time_plus_4 <- time_zero_intervention$time + 4
  
  # Where in the times after 0 intervention there is a 1 intervention
  starts_of_interventions <- final %>% 
    filter(id == i & time %in% time_plus_4) %>% 
    filter(intervention == 1)
  
  # Loop over each one of the times where intervention starts
  all_times <- list()
  for(n in 1:length(starts_of_interventions$time)) {
    # Gather 300 secs prior and post
    time_300_before <- starts_of_interventions$time[n] - 300
    time_300_after <- starts_of_interventions$time[n] + 300
    
    # Filter for observations in this interval
    all_times[[n]] <- final %>%
      filter(id == i) %>%
      filter(time >= time_300_before & time <= time_300_after)
  }
  if(length(all_times) == 1){
    obs_to_keep[[i]] <- as.data.frame(all_times)
  }
  else {
    obs_to_keep[[i]] <- do.call(rbind, all_times)
  }
}

# Make a data frame from the list
df <- do.call(rbind, obs_to_keep)

# Order it by id and time
df %<>% arrange(id, time)