dplyr 的“across”功能有多列输入版本吗?

问题描述 投票:0回答:3

我今天必须写一个这样的函数

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)))

但不幸的是,我的函数需要两列作为输入。有没有一种方法可以做到这一点,而无需为每组参数编写新行?

r dplyr
3个回答
5
投票

您可以使用

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)
}

5
投票

另一种使用重塑数据的方法。如果你能克服从更长的形式来回重塑的障碍,计算就会变得微不足道。

这种方法的一个好处是它对列顺序具有鲁棒性,并且您不需要预先指定列前缀,前提是您可以使用正则表达式指定一些常规模式。

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

4
投票

也许您可以尝试

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
}
© www.soinside.com 2019 - 2024. All rights reserved.