I want to map a function to each combination pair of variables in a dataframe in R, returning a dataframe with the function output for each pair. I can do this manually like so:
library(tidyverse)
df <- tibble(a = c(1, 2), b = c(4, 3), c = c(5, 7))
f <- function(a, b) a - b # a simple function for sake of example
df %>% transmute(a_minus_b = f(a, b),
a_minus_c = f(a, c),
b_minus_c = f(b, c),
b_minus_a = f(b, a),
c_minus_a = f(c, a),
c_minus_b = f(c, b))
Doing this manually is obviously impractical for a dataframe with many variables. How can I apply my function to each combination pair of variables using iteration?
Another approach using dplyr
and purrr
may look like so:
library(tidyverse)
df <- tibble(a = c(1, 2), b = c(4, 3), c = c(5, 7))
f <- function(a, b) a - b # a simple function for sake of example
f_help <- function(x) {
df %>%
transmute_at(setdiff(names(.), x), ~ f(!!sym(x), .x)) %>%
rename_all(.funs = ~ paste0(x, "_minus_", .x))
}
map(names(df), f_help) %>%
bind_cols()
#> # A tibble: 2 x 6
#> a_minus_b a_minus_c b_minus_a b_minus_c c_minus_a c_minus_b
#> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
#> 1 -3 -4 3 -1 4 1
#> 2 -1 -5 1 -4 5 4
One dplyr
and purrr
solution could be:
map_dfc(.x = c(combn(rev(names(df)), 2, simplify = FALSE),
combn(names(df), 2, simplify = FALSE)),
~ df %>%
rowwise() %>%
transmute(!!paste(.x, collapse = "_") := reduce(c_across(all_of(.x)), `-`)) %>%
ungroup())
c_b c_a b_a a_b a_c b_c
<dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 1 4 3 -3 -4 -1
2 4 5 1 -1 -5 -4
Or using the specified function:
map_dfc(.x = c(combn(rev(names(df)), 2, simplify = FALSE),
combn(names(df), 2, simplify = FALSE)),
~ df %>%
rowwise() %>%
transmute(!!paste(.x, collapse = "_") := reduce(c_across(all_of(.x)), f)) %>%
ungroup())
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With