We can try
i1 <- with(df, as.logical(ave(year, ID, FUN = function(x) { i1 <- (x[-1] - x[-length(x)]) ==1 i2 <- c(FALSE, i1) i3 <- c(i1, FALSE) rl <- rle(i2|i3) rl$values[rl$values][rl$lengths[rl$values] <5] <- FALSE rep(rl$values, rl$lengths) }))) df[i1,]
Or use data.table
library(data.table) i1 <- setDT(df)[, ind := (year - shift(year, fill= year[1L]))==1L , ID][, {i1 <- .I[.N * ind > 3] .(v1 = head(i1,1)-1, v2 = tail(i1, 1))}, .(ID, rl = rleid(ind))][, seq(v1, v2) , rl]$V1 df[, ind := NULL][i1] # ID year # 1: A 1984 # 2: A 1985 # 3: A 1986 # 4: A 1987 # 5: A 1988 # 6: A 1990 # 7: A 1991 # 8: A 1992 # 9: A 1993 #10: A 1994 #11: A 1995
Or a little compact option
i1 <- setDT(df)[, (shift(year, type="lead", fill = year[.N])-year)==1 | (year - shift(year, fill = year[1L]))==1, ID][, .I[.N>4 & V1] , .(rleid(V1), ID)]$V1 df[i1]
data
df <- data.frame( ID=c(rep("A", 20)), year=c(1968, 1971, 1972, 1973, 1974, 1976, 1978, 1980, 1982, 1984, 1985, 1986, 1987, 1988, 1990, 1991, 1992, 1993, 1994, 1995))