vendredi 30 octobre 2020

R dplyr conditional mutate with group_by

I have a grouped data.frame and want to mutate a column conditionally checking all() of the certain column.

In this example, I have a simple data.frame with 3 columns; I am grouping by the column code and if the column B of that group is entirely of NA, I want to copy the values from column A and otherwise keep the original non NA values of B.

Input:

> example <- tibble::tribble(
  ~code, ~A, ~B,
  "1", 0.5, 0.7,
  "1", 0.5, 0.3,
  "1", 0.5, 0.25,
  "2", 0.2, NA,
  "2", 0.8, NA,
  "2", 0.5, NA
)
> example %>% dplyr::group_by(code)
# A tibble: 6 x 3
# Groups:   code [2]
  code      A     B
  <chr> <dbl> <dbl>
1 1       0.5  0.7 
2 1       0.5  0.3 
3 1       0.5  0.25
4 2       0.2 NA   
5 2       0.8 NA   
6 2       0.5 NA   

Desired output:

# A tibble: 6 x 3
  code      A     B
  <chr> <dbl> <dbl>
1 1       0.5  0.7 
2 1       0.5  0.3 
3 1       0.5  0.25
4 2       0.2  0.2 
5 2       0.8  0.8 
6 2       0.5  0.5 

I've tried using ifelse() and it can check the all(is.na(B)) but it doesn't attribute rowwise as standard behavior and just copy from the first value.

example %>% 
  dplyr::group_by(code) %>%
  dplyr::mutate(
    B = ifelse(all(is.na(B)), A, B)
  )
# A tibble: 6 x 3
# Groups:   code [2]
  code      A     B
  <chr> <dbl> <dbl>
1 1       0.5   0.7
2 1       0.5   0.7
3 1       0.5   0.7
4 2       0.2   0.2
5 2       0.8   0.2
6 2       0.5   0.2

attribuing fixed values is ok.

example %>% 
  dplyr::group_by(code) %>%
  dplyr::mutate(
    isBna = ifelse(all(is.na(B)), 'y', 'n')
  )
# A tibble: 6 x 4
# Groups:   code [2]
  code      A     B isBna
  <chr> <dbl> <dbl> <chr>
1 1       0.5  0.7  n    
2 1       0.5  0.3  n    
3 1       0.5  0.25 n    
4 2       0.2 NA    y    
5 2       0.8 NA    y    
6 2       0.5 NA    y      

and with the dplyr::if_else() it throws an error complaning that A and B is not fixed value.

example %>% 
  dplyr::group_by(code) %>%
  dplyr::mutate(
    B = if_else(all(is.na(B)), A, B)
  )
Error: Problem with `mutate()` input `B`.
x `true` must be length 1 (length of `condition`), not 3.
ℹ Input `B` is `if_else(all(is.na(B)), A, B)`.
ℹ The error occurred in group 1: code = "1".
Run `rlang::last_error()` to see where the error occurred.     

and my real case error is little different.

# sometime like this
Error: Problem with `mutate()` input `xx`.
x `false` must be a logical vector, not a double vector.

# and sometimes like this
Error: Problem with `mutate()` input `xx`.
x `false` must be length 1 (length of `condition`), not 12.

Is there any way to achieve my goal within chains of pipe%>%?
Thanks in advance.

Aucun commentaire:

Enregistrer un commentaire