Search code examples
rrollapply

R - Insert a True every nth row based on previous rows


Test data Frame:

a<-data.frame(True_False = c(T,F,F,F,F,T,F,T,T,T,F,F,F,F,F,F,F,F))
  True_False
1        TRUE
2       FALSE
3       FALSE
4       FALSE
5       FALSE
6        TRUE
7       FALSE
8        TRUE
9        TRUE
10       TRUE
11      FALSE
12      FALSE
13      FALSE
14      FALSE
15      FALSE
16      FALSE
17      FALSE
18      FALSE

Using this, I would like to edit this column or make a new one which has a True at least once every third row. Meaning I would need to check the current row, if False, and if the previous two rows are False, then make it a True. Otherwise leave it as it is. Using Zoo, Dplyr, and Rollapply, I get close.

library(zoo)
library(tidyverse)
    b<-a%>%
  mutate(Roll = ifelse(rollapplyr(Input,3,sum, partial = T) == 0,T,Input))
b$Desired<-c(T,F,F,T,F,T,F,T,T,T,F,F,T,F,F,T,F,F)

   Input  Roll Desired
1   TRUE  TRUE    TRUE
2  FALSE FALSE   FALSE
3  FALSE FALSE   FALSE
4  FALSE  TRUE    TRUE
5  FALSE  TRUE   FALSE
6   TRUE  TRUE    TRUE
7  FALSE FALSE   FALSE
8   TRUE  TRUE    TRUE
9   TRUE  TRUE    TRUE
10  TRUE  TRUE    TRUE
11 FALSE FALSE   FALSE
12 FALSE FALSE   FALSE
13 FALSE  TRUE    TRUE
14 FALSE  TRUE   FALSE
15 FALSE  TRUE   FALSE
16 FALSE  TRUE    TRUE
17 FALSE  TRUE   FALSE
18 FALSE  TRUE   FALSE

Essentially my issue is that it will rollapply the sum to the whole column, and then add the Trues after. Thus, we have Trues that are not necessary. So is there a way I can do this in which the True is applied before going to the next row? I assume I need to use an apply of some sort, but that is an area I'm not familiar with, and even reading the documentation I'm not sure how to do this directly.


Solution

  • Due to the fact that you need to update your vector on the fly to process further operations, I'd say a simple for-loop is the way to go:

    for(i in 3:nrow(a)){
      a$True_False[i] <- ifelse(sum(a$True_False[(i-2):i]) == 0, T, a$True_False[i])
    }
    
    > a
       True_False
    1        TRUE
    2       FALSE
    3       FALSE
    4        TRUE
    5       FALSE
    6        TRUE
    7       FALSE
    8        TRUE
    9        TRUE
    10       TRUE
    11      FALSE
    12      FALSE
    13       TRUE
    14      FALSE
    15      FALSE
    16       TRUE
    17      FALSE
    18      FALSE