Как я могу использовать функциюthrough() в dplyr для применения пользовательских функций, возвращающих несколько столбцов?

Я изучаю функциюthrough(), представленную в последних версиях dplyr, и пытаюсь понять, как использовать ее для применения пользовательской функции, возвращающей несколько столбцов. В частности, я хочу применить функцию, которая вычисляет среднее и стандартное отклонение для выбранных числовых столбцов в моем фрейме данных и возвращает их как отдельные столбцы.

Например, учитывая следующий фрейм данных:

library(dplyr)

df <- data.frame(
  Group = rep(letters[1:3], each = 4),
  Value1 = rnorm(12, mean = 10, sd = 2),
  Value2 = rnorm(12, mean = 5, sd = 1)
)

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

  Group  Mean_Value1  SD_Value1  Mean_Value2  SD_Value2
1     a    9.812      2.034      4.955       1.085
2     b   10.231      1.987      5.023       0.923
3     c   10.032      2.121      4.998       1.098

Я попробовал следующий подход, но не уверен, как заставить его правильно работать с across():

df_summary <- df %>%
  group_by(Group) %>%
  summarise(across(starts_with("Value"), ~ c(mean = mean(.), sd = sd(.))))

Это вызывает ошибку, поскольку функцияthrough(), похоже, не обрабатывает естественным образом функции, возвращающие несколько столбцов.

Мои конкретные вопросы:

  1. Как я могу изменить этот подход, чтобы правильно использовать across() для функций, возвращающих несколько значений?
  2. Есть ли лучший способ добиться этого, используя dplyr или другой пакет в R?
  3. Каковы ограничения across() при работе с такими пользовательскими функциями?

Любые рекомендации о том, как это сделать, будут очень признательны!


50
2

Ответы:

Ваш вопрос фактически указан в качестве примера на странице документации сайта across.

Вам следует использовать list, чтобы включить несколько функций для across.

library(dplyr)

df %>%
  group_by(Group) %>%
  summarise(across(starts_with("Value"), list(mean = mean, sd = sd)))

# A tibble: 3 × 5
  Group Value1_mean Value1_sd Value2_mean Value2_sd
  <chr>       <dbl>     <dbl>       <dbl>     <dbl>
1 a            8.61     0.837        5.57     0.581
2 b            8.90     2.08         5.22     0.479
3 c           10.3      1.98         4.36     0.465

Решено

По адресу

Есть ли лучший способ добиться этого, используя dplyr или другой пакет в R?

Существует несколько пакетов, предоставляющих такие функции группировки. Если мы определим «лучше» как без использования внешних пакетов, мы сможем сделать:

aggregate(df[grepl("Value", names(df))], df["Group"], \(x) c(Mean=mean(x), SD=sd(x)))

предоставление

  Group Value1.Mean Value1.SD Value2.Mean Value2.SD
1     a   10.901248  2.365063   4.5826417 0.8582879
2     b    9.358671  2.549811   4.9142623 1.0512226
3     c   11.040255  1.491652   5.2339545 1.0130163

Это может быть альтернативой, если вас не беспокоит способ отображения aggregate() названий столбцов [отредактированный глагол].