Есть ли несколько столбцов в качестве входной версии dplyr `cross`?

Мне пришлось выполнить сегодня такую ​​функцию

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

Но, к сожалению, моей функции нужны два столбца в качестве входных данных. Есть ли способ сделать это более элегантно?

Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
4
0
65
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Возможно, вы можете попробовать 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)
}

ок, думаю, я могу обобщить это до аргумента 3 с помощью pmap

xiaodai 06.09.2024 00:04
map2_df устарел. Просто используйте map2, а затем unlist
xiaodai 06.09.2024 00:16

и я должен предположить, что столбцы расположены в правильном порядке? могу ли я организовать

xiaodai 06.09.2024 00:26

Другой подход с использованием измененных данных. Если вы сможете преодолеть препятствие, связанное с изменением формы более длинной формы, расчет будет тривиальным.

Одним из преимуществ этого подхода является то, что он устойчив к порядку столбцов, и вам не нужно заранее указывать префиксы столбцов, при условии, что существует некоторый регулярный шаблон, который можно указать с помощью регулярного выражения.

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

Другие вопросы по теме