Looking for a more idiomatic alternative

Given the tibble

t <- tibble(
 a=c('X', 'Y', 'X', 'Y', 'Z'),
 b=LETTERS[1:5],
 c = c(rep.int(3,2), rep.int(5,1), rep.int(2,2))
 )
# A tibble: 5 × 3
  a     b         c
  <chr> <chr> <dbl>
1 X     A         3
2 Y     B         3
3 X     C         5
4 Y     D         2
5 Z     E         2

Is there a more dplyr idiomatic way of writing the following code?

t |>
  mutate(
    b = if_else(
      a == 'X',
      b[which.max(c)][[1]],
      b
    )
  )

Thanks

If you mean just avoiding using which.max you could do something like this:

dplyr::mutate(
  tibble::tibble(
    a = c("X", "Y", "X", "Y", "Z"),
    b = LETTERS[1:5],
    c = c(rep.int(3, 2), rep.int(5, 1), rep.int(2, 2))
  ),
  b = dplyr::if_else(
    a == "X",
    dplyr::filter(
      dplyr::pick(tidyselect::everything()),
      a == "X"
    ) |>
      dplyr::slice_max(c, n = 1) |>
      dplyr::pull(b),
    b
  )
)
#> # A tibble: 5 × 3
#>   a     b         c
#>   <chr> <chr> <dbl>
#> 1 X     C         3
#> 2 Y     B         3
#> 3 X     C         5
#> 4 Y     D         2
#> 5 Z     E         2

But I kind of like the succinctness of how you wrote it above.

Created on 2024-08-30 with reprex v2.1.1.9000

1 Like

Thanks, yeah I agree that my code might be more readable. It is always good to know other ways of achieving the same result thought :grinning:

Here's another variation similar to @eric-hunt's:

library(tidyverse)
t <- tibble(
  a=c('X', 'Y', 'X', 'Y', 'Z'),
  b=LETTERS[1:5],
  c = c(rep.int(3,2), rep.int(5,1), rep.int(2,2))
)

t |> 
  mutate(
    temp = 
      t |> 
      slice_max(c) |> 
      pull(b),
    b = if_else(a == 'X', temp, b)
  ) |> 
  select(!temp)
#> # A tibble: 5 × 3
#>   a     b         c
#>   <chr> <chr> <dbl>
#> 1 X     C         3
#> 2 Y     B         3
#> 3 X     C         5
#> 4 Y     D         2
#> 5 Z     E         2

Created on 2024-08-31 with reprex v2.0.2

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.

If you have a query related to it or one of the replies, start a new topic and refer back with a link.