Имитация данных
# the data frame
# A tibble: 7 x 8
ID `2019-08-14` `2019-08-21` `2019-08-28` `2019-09-04` `2019-09-11` `2019-09-18` `2019-09-25`
<int> <int> <int> <int> <int> <int> <int> <int>
1 4188 1 1 0 0 1 1 1
2 9941 1 1 1 0 1 1 1
3 3989 1 0 0 1 1 1 1
4 8996 1 1 1 0 0 0 1
5 1234 1 1 1 1 1 1 1
6 2345 1 1 1 1 1 0 0
7 2345 0 0 1 1 1 0 0
Определение функции
Сложная часть для определения fcutnion, который преобразует шаблон 1,...,1
(где ...
должно быть 0 с любой длины) ввсе 1 с (1,....,1
).
rle
, кажется, пригодится в этом случае.
replace_pattern_101 <- function(vec){
stopifnot(length(setdiff(vec,c(0L,1L))) == 0L) # vec should only contain 0,1
# with rle(Run Length Encoding)
row_rle <- rle(vec)
row_rle_val <- row_rle$values
# patterns to find in `rle`, since the original vector has been already converted
# in rle, so numbe of 0s or 1s doesn't matter now.
pattern_101 <- c(1L,0L,1L)
# structure the original vector to a vec which we can used to find the pattern
# e.g c(1,0,1,0) to list(c(1,0,1),c(0,1,0))
rolling <- map(
seq(1:(length(row_rle_val) - length(pattern_101) + 1L)),
~ c(row_rle_val[.x:(.x+length(pattern_101)-1L)])
)
# find position that follows patter 1,0,1
match_index <- which(map_lgl(rolling, ~ identical(pattern_101,.x)))
if(length(match_index) > 0L) {
row_rle_val[match_index + 1L] <- 1L
row_rle$values <- row_rle_val
# inverse rle
inverse.rle(row_rle)
} else {
# otherwise return the original vector
return(vec)
}
}
> replace_pattern_101(c(0,0,1,1,0,0,0,1,0,1,0,0))
> [1] 0 0 1 1 1 1 1 1 1 1 0 0
Используйте pmap для итерации по строкам во фрейме данных.
Если у вас есть функция для замены шаблона, оставшийся шаг будет легким.
library(tidyverse)
pmap_df(df,function(...){
vals <- unlist(list(...))
num_vals <- as.integer(vals[-1])
num_vals
# restructure to a data.frame
as.list(c(
vals[1],
replace_pattern_101(num_vals) %>% setNames(names(vals)[-1])
))
})
Результаты
# A tibble: 7 x 8
ID `2019-08-14` `2019-08-21` `2019-08-28` `2019-09-04` `2019-09-11` `2019-09-18` `2019-09-25`
<int> <int> <int> <int> <int> <int> <int> <int>
1 4188 1 1 1 1 1 1 1
2 9941 1 1 1 1 1 1 1
3 3989 1 1 1 1 1 1 1
4 8996 1 1 1 1 1 1 1
5 1234 1 1 1 1 1 1 1
6 2345 1 1 1 1 1 0 0
7 2345 0 0 1 1 1 0 0
Данные
df <- structure(list(ID = c(4188L, 9941L, 3989L, 8996L, 1234L, 2345L,
2345L), `2019-08-14` = c(1L, 1L, 1L, 1L, 1L, 1L, 0L), `2019-08-21` = c(1L,
1L, 0L, 1L, 1L, 1L, 0L), `2019-08-28` = c(0L, 1L, 0L, 1L, 1L,
1L, 1L), `2019-09-04` = c(0L, 0L, 1L, 0L, 1L, 1L, 1L), `2019-09-11` = c(1L,
1L, 1L, 0L, 1L, 1L, 1L), `2019-09-18` = c(1L, 1L, 1L, 0L, 1L,
0L, 0L), `2019-09-25` = c(1L, 1L, 1L, 1L, 1L, 0L, 0L)), class = c("spec_tbl_df",
"tbl_df", "tbl", "data.frame"), row.names = c(NA, -7L))