переформатирование вывода dplyr summarise_at()

#r #dplyr

#r #dplyr

Вопрос:

Я использую summarise_at() для получения среднего значения и стандартной ошибки нескольких переменных по группам.

В выходных данных содержится 1 строка для каждой группы и 1 столбец для каждого вычисляемого количества для каждой группы. Я хотел бы иметь таблицу с 1 строкой для каждой переменной и 1 столбцом для каждого вычисляемого количества:

 data <- mtcars 

data$condition <- as.factor(c(rep("control", 16), rep("treat", 16))) 

data %>%  
group_by(condition) %>%
summarise_at(vars(mpg, cyl, wt), 
             funs(mean = mean, se=sd(.)/sqrt(n())))

# A tibble: 2 x 7
    condition mpg_mean cyl_mean wt_mean mpg_se cyl_se wt_se
    <fct>        <dbl>    <dbl>   <dbl>  <dbl>  <dbl> <dbl>        
  1 control       18.2     6.5     3.56   1.04  0.387 0.204
  2 treat         22.0     5.88    2.87   1.77  0.499 0.257
  

Вот что, я думаю, было бы более полезным (цифры не имеют смысла):

 #        MEAN.control, MEAN.treat, SE.control, SE.treat
# mpg         1.5          2.4         .30       .45             
# cyl         3.2          1.9         .20       .60  
# disp        12.3         17.8        .20       .19
  

Есть идеи? Новичок в tidyverse , так что извините, если это слишком просто.

Ответ №1:

funs Становится устаревшим в dplyr . Вместо этого используйте list in summarise_at/mutate_at . После summarise шага gather данные переводятся в формат ‘long’, separate столбец ‘key’ разделяется на два с помощью разделителя _ , затем unite ‘cond’ и ‘key2’ (после изменения регистра ‘key2’), spread это в формат ‘wide’ и, при необходимости, измените имена строк на столбец ‘key1’

 library(tidyverse)
data %>% 
   group_by(condition) %>%
   summarise_at(vars(mpg, cyl, wt), list(MEAN = ~ mean(.), 
                                    SE = ~sd(.)/sqrt(n()))) %>% 
   gather(key, val, -condition) %>% 
   separate(key, into = c("key1", "key2")) %>%        
   unite(cond, key2, condition, sep=".") %>% 
   spread(cond, val) %>%
   column_to_rownames('key1')
#    MEAN.control MEAN.treat SE.control  SE.treat
#cyl     6.500000   5.875000  0.3872983 0.4989572
#mpg    18.200000  21.981250  1.0369024 1.7720332
#wt      3.560875   2.873625  0.2044885 0.2571034
  

Комментарии:

1. Любопытно, почему было funs изменено на list ?!

2. @NelsonGon Я нахожу здесь открытую проблему, но причина не указана

3. Спасибо!! Я также обновил пример в свете вашего комментария. Я ценю это.

4. @BrianGuay Спасибо за обновление. Но я вижу, что значения отличаются. Это ожидаемый результат

Ответ №2:

Другая возможность может быть:

 data %>%  
 group_by(condition) %>%
 summarise_at(vars(mpg, cyl, wt), list(mean = ~ mean(.), 
                                       se = ~ sd(.)/sqrt(n()))) %>% 
 gather(var, val, -condition) %>%
 separate(var, c("vars", "var2")) %>%
 mutate(var2 = paste(toupper(var2), as.character(condition), sep = "_")) %>%
 select(-condition) %>%
 spread(var2, val)

  vars  MEAN_control MEAN_treat SE_control SE_treat
  <chr>        <dbl>      <dbl>      <dbl>    <dbl>
1 cyl           6.5        5.88      0.387    0.499
2 mpg          18.2       22.0       1.04     1.77 
3 wt            3.56       2.87      0.204    0.257
  

Здесь, после ваших начальных шагов, выполняется преобразование данных от широкого к длинному, исключая столбец «условие». Во-вторых, он разделяет имена переменных на два столбца. В-третьих, он объединяет метрику и условие, причем метрика указывается в верхнем регистре. Наконец, это удаляет избыточную переменную и возвращает ее к желаемому формату.

Или вы можете избежать этого separate() , используя некоторое регулярное выражение:

 data %>%  
 group_by(condition) %>%
 summarise_at(vars(mpg, cyl, wt), list(mean = ~ mean(.), 
                                       se = ~ sd(.)/sqrt(n()))) %>% 
 gather(var, val, -condition) %>%
 mutate(vars = gsub("_.*$", "", var),
        var2 = gsub(".*\_", "", var)) %>%
 mutate(var2 = paste(toupper(var2), as.character(condition), sep = "_")) %>%
 select(-condition, -var) %>%
 spread(var2, val)
  

Или с помощью strsplit() :

 data %>%  
 group_by(condition) %>%
 summarise_at(vars(mpg, cyl, wt), list(mean = ~ mean(.), 
                                       se = ~ sd(.)/sqrt(n()))) %>% 
 gather(var, val, -condition) %>%
 mutate(vars = sapply(strsplit(var, "_"), function(x) x[1]),
        var2 = sapply(strsplit(var, "_"), function(x) x[2])) %>%
 mutate(var2 = paste(toupper(var2), as.character(condition), sep = "_")) %>%
 select(-condition, -var) %>%
 spread(var2, val)
  

Или вы можете полностью переписать его в:

 data %>%
 select(mpg, cyl, wt, condition) %>%
 gather(vars, val, -condition) %>%
 group_by(condition, vars) %>%
 summarise(mean = mean(val),
           se = sd(val)/sqrt(n())) %>%
 ungroup() %>%
 gather(var2, val, -c(condition, vars)) %>%
 mutate(var2 = paste(toupper(var2), condition, sep = "_")) %>%
 select(-condition) %>%
 spread(var2, val)
  

В этом случае сначала выбираются интересующие переменные. Во-вторых, он выполняет преобразование из широкого формата в длинный, исключая столбец «условие». В-третьих, он группирует по условиям и именам переменных и вычисляет показатели. На четвертом шаге выполняется второе преобразование от широкого к длинному, исключая столбец «условие» и столбец с начальными именами переменных. Наконец, он объединяет метрику (верхний регистр) и условие, удаляет избыточную переменную и возвращает ее к желаемому формату.