Лишние столбцы, возвращаемые функцией dplyr::summarise()

#r #dplyr

#r #dplyr

Вопрос:

У меня возникли некоторые проблемы с новой dplyr::summarise() функцией

Вот данные

 df <- data.frame(id = factor(1:10),
                 group = factor(rep(letters[1:2],each = 5)),
                 w1 = rnorm(10),
                 w2 = rnorm(10),
                 w3 = rnorm(10),
                 dummy = as.character(LETTERS[1:10]),
                 stringsAsFactors = F)
  

Теперь я хочу получить средние значения и стандартные отклонения только для числовых переменных. Итак, я выполнил следующий код

 df %>% 
  dplyr::select(id, group, w1:w3) %>% 
    group_by(group) %>%
      dplyr::summarise(across(where(is.numeric), ~ mean(.x, na.rm = T), .names = "mean_{col}"),
                       across(where(is.numeric), ~ sd(.x, na.rm = T), .names = "sd_{col}"),
                       count = n())
  

Что дает мне следующий результат

 # A tibble: 2 x 11
# group mean_w1 mean_w2 mean_w3 sd_w1 sd_w2 sd_w3 sd_mean_w1 sd_mean_w2 sd_mean_w3 count
# <fct>   <dbl>   <dbl>   <dbl> <dbl> <dbl> <dbl>      <dbl>      <dbl>      <dbl> <int>
# a      -0.399   0.152 -0.151   1.07 0.703 1.15          NA         NA         NA     5
# b       0.560  -0.107 -0.0439  1.18 0.612 0.862         NA         NA         NA     5
  

Теперь столбцы, начинающиеся с mean_ и sd_ , — это именно то, что я хочу, но я также получаю этот набор sd_mean_ столбцов, я полагаю, потому что он пытается найти sd для новых mean_ столбцов.

Как мне получить выходные данные без лишних столбцов?

Ответ №1:

Проблема в том, что при переходе ко второму, across количество числовых столбцов увеличилось, поэтому он применяет sd функцию и к новым столбцам. Чтобы избежать этого, примените несколько функций в одном и том же across использовании list() .

 library(dplyr)

df %>% 
  group_by(group) %>%
  summarise(across(where(is.numeric), list(mean = ~mean(., na.rm = TRUE), 
                                           sd = ~sd(., na.rm = TRUE)),
                                           .names = "{fn}_{col}"), 
             count = n())

#  group mean_w1 sd_w1 mean_w2 sd_w2 mean_w3 sd_w3 count
#  <fct>   <dbl> <dbl>   <dbl> <dbl>   <dbl> <dbl> <int>
#1 a      0.0746 0.696  0.760  1.39   0.0530  1.29     5
#2 b      0.522  0.686  0.0979 0.566 -0.0133  1.12     5
  

Кроме того, ваша попытка будет работать должным образом, если вы не выберете столбцы по их типу :

 df %>% 
  group_by(group) %>%
  summarise(across(w1:w3, ~ mean(.x, na.rm = T), .names = "mean_{col}"),
            across(w1:w3, ~ sd(.x, na.rm = T), .names = "sd_{col}"),
            count = n())