R: How to intercalate rows by condition?

Viewed 92

Say if we have a dataframe looking like this:

A         B          C           D
XX        WW         0           0
XX        WW         0           1
WW        XX         0           1
XX        WW         1           1
XX        WW         1           0
YY        ZZ         0           1
YY        ZZ         0           1
ZZ        YY         1           0
YY        ZZ         1           1

I would like to add a new row down to each one in which D equals 1 and A and B remain unchanged into the following one. The rule that should follow the entire table is that whenever D equals one, A and B should invert its values into the following one, assuming C and D will equal 0 into these newly introduced rows. In this example, my desired output should look this way:

A         B          C           D
XX        WW         0           0
XX        WW         0           1
WW        XX         0           1
XX        WW         1           1
WW        XX         0           0
XX        WW         1           0
YY        ZZ         0           1
ZZ        YY         0           0
YY        ZZ         0           1
ZZ        YY         1           0
YY        ZZ         1           1

I've been unsuccessfully trying with dplyr and tidyr, any piece of help will be more than appreciated.

1 Answers

I'm not entirely sure this follows your logic but may be close.

The first mutate is to store the A column to swap A and B.

The group_by will create groups after which a new row will be inserted with rbind. A and B will be swapped, and C and D will be set to zero.

library(tidyverse)

df %>%
  mutate(tmp = A) %>%
  group_by(
    grp = cumsum(A == lag(A, default = "") & B == lag(B, default = "") & lag(D) == 1)
  ) %>%
  do(
    rbind(
      mutate(
        head(., 1), A = B, B = tmp, C = 0, D = 0
      ), .
    )
  ) %>%
  ungroup %>%
  slice(-1) %>%
  select(-grp, -tmp)

Output

   A     B         C     D
   <chr> <chr> <dbl> <dbl>
 1 XX    WW        0     0
 2 XX    WW        0     1
 3 WW    XX        0     1
 4 XX    WW        1     1
 5 WW    XX        0     0
 6 XX    WW        1     0
 7 YY    ZZ        0     1
 8 ZZ    YY        0     0
 9 YY    ZZ        0     1
10 ZZ    YY        1     0
11 YY    ZZ        1     1
Related