The problem: I need to create a new variable (eventWindowTime) in R that is based on data from two columns - obstacle present (1=yes,0=no) and timeOnTask (assessed continuously).
The dataset: I have data that was continuously collected (to the fractional seconds) from several participants as they performed a task. At various points, participants encountered one or more obstacles. I would like to create obstacle event windows that range from -5s (5 s before the obstacle) to +20s (20 s after the obstacle).
Additional challenges:
- Some event windows are overlapping
- Some timestamps have multiple measurements (so I can't rep values -5 to 20 relative to the first obstaclePresent == 1)
Things I've tried: The way I would typically approach this is to use ifelse or case_when functions with lag() to:
- set eventWindowTime to 0 when obstaclePresent == 1 && lag(obstaclePresent == 0)
- set eventWindow Time to increment the lagged eventWindowTime value by the difference in timeOnTask values across the two rows when obstaclePresent == 1 && lag(obstaclePresent == 1).
- then backfill the negative seconds in a second step.
However, R does not seem to hold the lagged values in memory and I keep getting a "Error in vec_slice():
! x must be a vector, not NULL." error.
Here's a small subset of code and a file which can be used to reproduce the problem:
mre <- data.frame(Sub = rep(1, 41), Time = c(723.2, 723.2, 723.3, 723.3, 723.3, 723.4, 723.4, 723.5, 723.5, 723.6, 723.6, 723.6, 723.7, 723.7, 723.7, 723.8, 723.9, 723.9, 723.9, 724, 724, 724, 724, 724.1, 724.1, 724.2, 724.2, 724.2, 724.3, 724.3, 724.3, 724.4, 724.4, 724.5, 724.5, 724.6, 724.6, 724.6, 724.7, 724.7, 724.8), obstaclePresent = c(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1))
mre$obstacleEventWindow <- case_when(
mre$obstaclePresent != lag(mre$obstaclePresent,1) & mre$obstaclePresent == 0 ~ 0,
mre$obstaclePresent == lag(mre$obstaclePresent,1) ~ lag(mre$obstacleEventWindow) + mre$newTime - lag(mre$newTime,1),
TRUE ~ 0
)
To be clear, I understand that the case_when() statement is self-referencing. I've worked with other programs where a column is populated on the fly, and you can reference lagged cells without issue. That isn't working here, but I'm at a loss with respect to what to do instead.