Мне пришлось выполнить сегодня такую функцию
data1 %>%
summarise(
ab1 = fn(a1, b1),
ab2 = fn(a2, b2),
ab3 = fn(a3, b3)
)
# imagine if there are 100 of them
Если бы fn
была функцией с одним аргументом, я мог бы сделать
data1 %>%
summarise(across(starts_with("a", fn)))
Но, к сожалению, моей функции нужны два столбца в качестве входных данных. Есть ли способ сделать это более элегантно?
Возможно, вы можете попробовать split.default
разбить столбцы на группы по их именам, например,
data1 %>%
split.default(sub("\\D+", "ab", names(.))) %>%
map_dfr(\(...) do.call(fn, unname(...)))
что дает
# A tibble: 3 × 3
ab1 ab2 ab3
<dbl> <dbl> <dbl>
1 4 70 208
2 10 88 238
3 18 108 270
data1 <- data.frame(
a1 = c(1, 2, 3),
b1 = c(4, 5, 6),
a2 = c(7, 8, 9),
b2 = c(10, 11, 12),
a3 = c(13, 14, 15),
b3 = c(16, 17, 18)
)
fn <- function(a, b) {
a * b
}
Вы можете использовать функции map2*
для передачи двух наборов столбцов.
library(dplyr)
library(purrr)
data1 %>%
summarise(map2_df(pick(starts_with("a")), pick(starts_with("b")), fn))
# a1 a2 a3
#1 21 57 93
Использование данных из @ThomasIsCoding, но другой функции, поскольку ваш код использует summarise
, это означает, что в конце у него будет одна строка.
fn <- function(a, b) {
sum(a, b)
}
map2_df
устарел. Просто используйте map2
, а затем unlist
и я должен предположить, что столбцы расположены в правильном порядке? могу ли я организовать
Другой подход с использованием измененных данных. Если вы сможете преодолеть препятствие, связанное с изменением формы более длинной формы, расчет будет тривиальным.
Одним из преимуществ этого подхода является то, что он устойчив к порядку столбцов, и вам не нужно заранее указывать префиксы столбцов, при условии, что существует некоторый регулярный шаблон, который можно указать с помощью регулярного выражения.
library(tidyverse)
data1 |>
# reshape long, in this case assuming the columns are all (letters)(numbers).
mutate(row = row_number()) |>
pivot_longer(cols = -row,
names_to = c(".value", "Pair"),
names_pattern = "(\\D+)(\\d+)") |>
# do the calculation with the two or more involved columns
mutate(ab = a*b, .by = c(row, Pair)) |>
# reshape wider again
pivot_wider(names_from = Pair, names_glue = "{.value}{Pair}", names_vary = "slowest",
values_from = a:ab)
Вывод с использованием данных из @ThomasIsCoding:
row a1 b1 ab1 a2 b2 ab2 a3 b3 ab3
<int> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 1 1 4 4 7 10 70 13 16 208
2 2 2 5 10 8 11 88 14 17 238
3 3 3 6 18 9 12 108 15 18 270
ок, думаю, я могу обобщить это до аргумента 3 с помощью
pmap