Trying to create "On" / "Off" based on difference between values in order-sorted list

rstudio

#1

I have a dataset similar to:

Name, Day, Score, Diff
Jain, 1, 8, 0
Jain, 2, 6, -2
Jain, 3, 8, 2
Jain, 4, 12, 4
Jain, 5, 13, 1
Jain, 6, 6, -7
Matt, 1,4, 0
Matt, 2, 10, 6
Matt, 3, 11, 1
Matt, 4, 12, 1
Matt, 5, 5, -7
Matt, 6, 6, 1

I want to add a new column which will record "Off" when a score difference drops 3 points, until there's a gain of +3 points, which will then record "On" until there's a drop.

Example:

Name, Day, Score, Diff, OnOff
Jain, 1, 8, 0, "Off"
Jain, 2, 6, -2, "Off"
Jain, 3, 8, 2, "Off"
Jain, 4, 12, 4, "On"
Jain, 5, 13, 1, "On"
Jain, 6, 6, -7, "Off"
Matt, 1,4, 0, "Off"
Matt, 2, 10, 6, "On"
Matt, 3, 11, 1, "On"
Matt, 4, 12, 1, "On"
Matt, 5, 5, -7, "Off"
Matt, 6, 6, 1, "Off"

Can't seem to figure out how to code this one. I've attempted with the following:

df$OnOff <- ifelse(df$Diff >= 3, "On", ifelse(df$Diff <= -3, "Off", ""))
df$OnOff <- ifelse(df$OnOff == "", lag(df$OnOff), df$OnOff)

#2

Not super elegant, but this works:

data
library(tidyverse)

df <- tribble(
  ~Name, ~Day, ~Score, ~Diff,
  "Jain", 1, 8, 0,
  "Jain", 2, 6, -2,
  "Jain", 3, 8, 2,
  "Jain", 4, 12, 4,
  "Jain", 5, 13, 1,
  "Jain", 6, 6, -7,
  "Matt", 1,4, 0,
  "Matt", 2, 10, 6,
  "Matt", 3, 11, 1,
  "Matt", 4, 12, 1,
  "Matt", 5, 5, -7,
  "Matt", 6, 6, 1)
df2 <-
  df %>%
  mutate(OnOff = case_when(
    # Special case for initial condition
    row_number() == 1 & Diff > -3 & Diff < 3  ~ "Off", 
    Diff <= -3 ~ "Off",
    Diff >=  3 ~ "On",
    TRUE ~ NA_character_ # NA's when no change in OnOff
  )) %>%
  fill(OnOff) # When NA in OnOff, use prior value