Skip to content

Instantly share code, notes, and snippets.

@jennybc
Last active February 25, 2021 07:05
Show Gist options
  • Save jennybc/f1eca9460e106914a836b2ea32f0279e to your computer and use it in GitHub Desktop.
Save jennybc/f1eca9460e106914a836b2ea32f0279e to your computer and use it in GitHub Desktop.
A rowwise summary problem where we don't want to use `rowwise()`
library(tidyverse)

(df <- tibble(
  id = 1:3,
  wut = letters[3:1],
  x1 = 1:3,
  x2 = 4:6,
  x3 = 7:9
))
#> # A tibble: 3 x 5
#>      id wut      x1    x2    x3
#>   <int> <chr> <int> <int> <int>
#> 1     1 c         1     4     7
#> 2     2 b         2     5     8
#> 3     3 a         3     6     9

col_prod <- function(...) {
  args <- list(...)
  Reduce(`*`, args)
}

df %>%
  mutate(y = pmap_dbl(select(., starts_with("x")), col_prod))
#> # A tibble: 3 x 6
#>      id wut      x1    x2    x3     y
#>   <int> <chr> <int> <int> <int> <dbl>
#> 1     1 c         1     4     7    28
#> 2     2 b         2     5     8    80
#> 3     3 a         3     6     9   162

df %>%
  mutate(y = pmap_dbl(across(starts_with("x")), col_prod))
#> # A tibble: 3 x 6
#>      id wut      x1    x2    x3     y
#>   <int> <chr> <int> <int> <int> <dbl>
#> 1     1 c         1     4     7    28
#> 2     2 b         2     5     8    80
#> 3     3 a         3     6     9   162

Created on 2021-02-24 by the reprex package (v1.0.0.9002)

@mattansb
Copy link

Wouldn't it be safer to use across(...) instead if select (.,...)?

@jennybc
Copy link
Author

jennybc commented Feb 25, 2021

Yeah that's cleaner (added above). I'm not sure I understand the safety concern.

Also not sure that this is meaningfully different than a rowwise() solution (but I think we've only had partial information about the context).

@mattansb
Copy link

It's safer because it "respects" previous changes in mutate.

For example, I've added a transformation on x1, but only the across solution "caught" this in the computation of y:

library(tidyverse)

(df <- tibble(
  id = 1:3,
  wut = letters[3:1],
  x1 = 1:3,
  x2 = 4:6,
  x3 = 7:9
))
#> # A tibble: 3 x 5
#>      id wut      x1    x2    x3
#>   <int> <chr> <int> <int> <int>
#> 1     1 c         1     4     7
#> 2     2 b         2     5     8
#> 3     3 a         3     6     9

col_prod <- function(...) {
  args <- list(...)
  Reduce(`*`, args)
}

df %>%
  mutate(x1 = exp(x1),
         y = pmap_dbl(select(., starts_with("x")), col_prod))
#> # A tibble: 3 x 6
#>      id wut      x1    x2    x3     y
#>   <int> <chr> <dbl> <int> <int> <dbl>
#> 1     1 c      2.72     4     7    28
#> 2     2 b      7.39     5     8    80
#> 3     3 a     20.1      6     9   162

df %>%
  mutate(x1 = exp(x1),
         y = pmap_dbl(across(starts_with("x")), col_prod))
#> # A tibble: 3 x 6
#>      id wut      x1    x2    x3      y
#>   <int> <chr> <dbl> <int> <int>  <dbl>
#> 1     1 c      2.72     4     7   76.1
#> 2     2 b      7.39     5     8  296. 
#> 3     3 a     20.1      6     9 1085.

Created on 2021-02-25 by the reprex package (v1.0.0)

@jennybc
Copy link
Author

jennybc commented Feb 25, 2021

It's safer because it "respects" previous changes in mutate

Yeah, true.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment