Мы можем использовать rleid
из data.table
, чтобы получить идентификатор длины кодировки, основанный на разнице в соседних элементах столбца, а затем получить индекс строки (.I
), где выполняется условие, и обновите «Зону», указав индекс в i
при обновлении «Зоны» на 1
library(data.table)
i1 <- setDT(df)[, grp := rleid(Zone)][, .I[Zone == 0 & .N <=2], grp]$V1
df[i1, Zone := 1][, grp := NULL][]
# Zone
# 1: 0
# 2: 0
# 3: 0
# 4: 1
# 5: 1
# 6: 1
# 7: 1
# 8: 1
# 9: 1
#10: 1
#11: 1
#12: 1
#13: 1
#14: 1
#15: 1
#16: 1
#17: 1
#18: 1
#19: 1
#20: 1
#21: 0
#22: 0
#23: 0
#24: 1
#25: 1
Или используя dplyr
, создав группу, сравнивающую соседние элементы, а затем заменив значение с помощью case_when
library(dplyr)
df %>%
group_by(grp = cumsum(Zone != lag(Zone, default = first(Zone)))) %>%
mutate(Zone = case_when(Zone == 0 & n() <=2 ~ 1, TRUE ~Zone)) %>%
ungroup %>%
select(-grp)
Или с использованием rle/inverse.rle
из base R
inverse.rle(within.list(rle(df$Zone), values[values== 0 & lengths <=2] <- 1))
#[1] 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 1 1
Или его можно сделать слегка компактным с помощью
with(rle(df$Zone), +(rep((!values & lengths <=2)|values, lengths)))
данные
df <- structure(list(Zone = c(0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1,
1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1)), row.names = c(NA, -25L),
class = "data.frame")