Home > Enterprise >  Is there a efficient way to mutate only on rows that meet a condition? Think mute(when(condition))
Is there a efficient way to mutate only on rows that meet a condition? Think mute(when(condition))

Time:11-24

I am looking to apply a mutate only when certain conditions are met.

I know I can do this...

data2 <- data1 %>%
   group_by(a, b) %>%
   mutate(
      var1 = case_when(
         condition ~ TRUE,
         TRUE ~ FALSE,
         NA
         ),
      var2 = case_when(
         condition ~ TRUE,
         max(var28),
         var2
         ),
      var3 = case_when(
         condition ~ TRUE,
         "happy",
         var3
         ),
...more vars here....
)

What I would like is something that looks like this...

data2 <- data1 %>%
   group_by(a, b) %>%
   mutate(
      when(condition),
      var1 = FALSE,
      var2 = max(var28),
      var3 = "happy",
...more vars here....
)

Unfortunately mutate(across(when(condition))) did not work.

Any suggesions?

CodePudding user response:

There is no functionality to do this in mutate, but Romain Francois has shared a function you could define yourself which does this:

library(dplyr, warn.conflicts = F)

mutate_when <- function(.data, when, ...) {
  dots <- enquos(...)
  names <- names(dots)
  
  mutate(.data, {
    test <- {{ when }}
    
    changed <- data.frame(!!!dots, stringsAsFactors = FALSE)
    out <- across(all_of(names))
    # assuming `changed` and `out` have the same data frame type

    out[test, ] <- changed[test, ]
    out
  })
  
}

tibble(x = 1:4, y = 1:4) %>% 
  mutate_when(x < 4, x = -x, y = -y)
#> # A tibble: 4 × 2
#>       x     y
#>   <int> <int>
#> 1    -1    -1
#> 2    -2    -2
#> 3    -3    -3
#> 4     4     4

Created on 2021-11-23 by the reprex package (v2.0.1)

  • Related