Home > other >  How to Filter by group and move all values to new column if any value in any of the affected columns
How to Filter by group and move all values to new column if any value in any of the affected columns

Time:11-08

I have a Datafaame like this:

 dt <- tibble(
 TRIAL = c("A", "A", "A", "B", "B", "B", "C", "C", "C","D","D","D"),
 RL = c(1, NA, 3, 1, 6, 3, 2, 3, 1, 0, 1.5, NA),
 SL = c(6, 1.5, 1, 0, 0, 1, 1, 2, 0, 1, 1.5, NA),
 HC = c(0, 1, 5, 6,7, 8, 9, 3, 4, 5, 4, 2)
 )


# A tibble: 12 x 4
  TRIAL    RL    SL    HC
  <chr> <dbl> <dbl> <dbl>
  1 A       1     6       0
  2 A      NA     1.5     1
  3 A       3     1       5
  4 B       1     0       6
  5 B       6     0       7
  6 B       3     1       8
  7 C       2     1       9
  8 C       3     2       3
  9 C       1     0       4
 10 D       0     1       5
 11 D       1.5   1.5     4
 12 D      NA    NA       2

I want to group the data frame by TRIAL and have the values in RL and SL checked by group, if the value in either of the column is greater than 5 then move all values for RL and SL for that particular group to RLCT and SLCT respectively.

# A tibble: 12 x 6
TRIAL    HC  RLCT  SLCT    SL    RL
<chr> <dbl> <dbl> <dbl> <dbl> <dbl>
 1 A         0     1   6    NA    NA  
 2 A         1    NA   1.5  NA    NA  
 3 A         5     3   1    NA    NA  
 4 B         6     1   0    NA    NA  
 5 B         7     6   0    NA    NA  
 6 B         8     3   1    NA    NA  
 7 C         9    NA  NA     1     3  
 8 C         3    NA  NA     3     5  
 9 C         4    NA  NA     1     1  
10 D         5    NA  NA     1     0  
11 D         4    NA  NA     1.5   1.5
12 D         2    NA  NA    NA    NA 

When I run the below code, I did not get the expected output

dt0 <- dt %>%
   mutate(RLCT = NA,
          SLCT = NA) %>%
   group_by(TRIAL) %>%
   filter(!any(RL > 5.0 | SL > 5.0))
dt1 <- dt %>%
   group_by(TRIAL) %>%
   filter(any(RL > 5.0 | SL > 5.0)) %>%
   mutate(RLCT = RL,
          SLCT = SL) %>%
   rbind(dt0, .) %>%
   mutate(RL = ifelse(!is.na(RLCT), NA, RL),
          SL = ifelse(!is.na(SLCT), NA, SL)) %>% arrange(TRIAL)
 

This is what I get

# A tibble: 9 x 6
# Groups:   TRIAL [3]
   TRIAL    RL    SL    HC  RLCT  SLCT
   <chr> <dbl> <dbl> <dbl> <dbl> <dbl>
 1 A        NA    NA     0     1   6  
 2 A        NA    NA     1    NA   1.5
 3 A        NA    NA     5     3   1  
 4 B        NA    NA     6     1   0  
 5 B        NA    NA     7     6   0  
 6 B        NA    NA     8     3   1  
 7 C         2     1     9    NA  NA  
 8 C         3     2     3    NA  NA  
 9 C         1     0     4    NA  NA  

CodePudding user response:

You can define a column to storage the condition, and change RL and SL with ifelse inside across.

dt %>%
  group_by(TRIAL) %>%
  mutate(cond = any(RL > 5.0 | SL > 5.0, na.rm = TRUE),
         across(c(RL, SL), ~ ifelse(cond, ., NA), .names = "{.col}CT"),
         across(c(RL, SL), ~ ifelse(!cond, ., NA)),
         cond = NULL)

Result:

# A tibble: 12 x 6
# Groups:   TRIAL [4]
   TRIAL    RL    SL    HC  RLCT  SLCT
   <chr> <dbl> <dbl> <dbl> <dbl> <dbl>
 1 A      NA    NA       0     1   6  
 2 A      NA    NA       1    NA   1.5
 3 A      NA    NA       5     3   1  
 4 B      NA    NA       6     1   0  
 5 B      NA    NA       7     6   0  
 6 B      NA    NA       8     3   1  
 7 C       2     1       9    NA  NA  
 8 C       3     2       3    NA  NA  
 9 C       1     0       4    NA  NA  
10 D       0     1       5    NA  NA  
11 D       1.5   1.5     4    NA  NA  
12 D      NA    NA       2    NA  NA  

CodePudding user response:

With dplyr, you could use group_modify():

library(dplyr)

dt %>%
  group_by(TRIAL) %>%
  group_modify(~ {
    if(any(select(.x, c(RL, SL)) > 5, na.rm = TRUE)) {
      rename_with(.x, ~ paste0(.x, 'CT'), c(RL, SL))
    } else {
      .x
    }
  })
Output
# A tibble: 12 × 6
# Groups:   TRIAL [4]
   TRIAL  RLCT  SLCT    HC    RL    SL
   <chr> <dbl> <dbl> <dbl> <dbl> <dbl>
 1 A         1   6       0  NA    NA  
 2 A        NA   1.5     1  NA    NA  
 3 A         3   1       5  NA    NA  
 4 B         1   0       6  NA    NA  
 5 B         6   0       7  NA    NA  
 6 B         3   1       8  NA    NA  
 7 C        NA  NA       9   2     1  
 8 C        NA  NA       3   3     2  
 9 C        NA  NA       4   1     0  
10 D        NA  NA       5   0     1  
11 D        NA  NA       4   1.5   1.5
12 D        NA  NA       2  NA    NA
  •  Tags:  
  • r
  • Related