我想将一个函数映射到 R 中数据帧中的每个变量组合对,返回一个带有每对函数输出的数据帧。我可以像这样手动执行此操作:
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))
Run Code Online (Sandbox Code Playgroud)
对于具有许多变量的数据框,手动执行此操作显然是不切实际的。如何使用迭代将我的函数应用于每个变量组合对?
另一种使用dplyr
和 的方法purrr
可能如下所示:
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
Run Code Online (Sandbox Code Playgroud)
一种dplyr
和purrr
解决方案可能是:
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
Run Code Online (Sandbox Code Playgroud)
或者使用指定的函数:
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())
Run Code Online (Sandbox Code Playgroud)
使用 tidyverseset_names
library(tidyverse)
f <- function(a, b) a - b # a simple function for sake of example
c(combn(df, 2, simplify = F),
combn(rev(df), 2, simplify = F)) %>%
set_names(map_chr(., ~paste(names(.), collapse = "_minus_"))) %>%
map(., ~f(.x[1], .x[2]) %>% pull) %>%
bind_cols()
# A tibble: 2 x 6
a_minus_b a_minus_c b_minus_c c_minus_b c_minus_a b_minus_a
<dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 -3 -4 -1 1 4 3
2 -1 -5 -4 4 5 1
Run Code Online (Sandbox Code Playgroud)