Мы можем использовать slice
после группировки по 'ID'
library(dplyr)
df %>%
group_by(ID) %>%
slice(which(Year <= Year[match("yyy", Program)]))
# A tibble: 5 x 3
# Groups: ID [2]
# ID Program Year
# <chr> <chr> <int>
#1 ABC xxx 2000
#2 ABC yyy 2001
#3 DEF xxx 2000
#4 DEF zzz 2001
#5 DEF yyy 2002
или используя data.table
library(data.table)
setDT(df)[, .SD[Year <= Year[match("yyy", Program)]], ID]
data
df <- structure(list(ID = c("ABC", "ABC", "ABC", "DEF", "DEF", "DEF"
), Program = c("xxx", "yyy", "zzz", "xxx", "zzz", "yyy"), Year = c(2000L,
2001L, 2002L, 2000L, 2001L, 2002L)), class = "data.frame", row.names = c(NA,
-6L))