Ищете функцию или формулу для создания таблицы со средними значениями и стандартными отклонениями для многих групп и многих переменных с помощью tidyverse - PullRequest
0 голосов
/ 28 мая 2020

Мне нужно подготовить таблицу, которая включает средние и стандартные отклонения для каждого уровня нескольких демографических c переменных и для многих переменных.

Рассмотрим следующие данные:

df <- tibble(place=c("London","Paris","London","Rome","Rome","Madrid","Madrid"),gender=c("m","f","f","f","m","m","f"), education = c(1,1,2,3,5,5,3), var1 = c(2.2,3.1,4.5,1,5,1.4,2.3),var2 = c(4.2,2.1,2.5,4,5,4.4,1.3),var3 = c(0.2,0.1,3.5,3,5,2.4,4.3))

Я хотел бы получить фрейм данных, содержащий группирующие переменные (место, пол, образование) и их уровни (например, , London, Paris, et al. c.) в первом столбце , а их средние значения и стандартные отклонения для каждой переменной, начинающейся с var (var1, var2, var3), в дополнительных столбцах.

Я знаю, как сделать это для одной группы и нескольких переменных одновременно. Однако, поскольку мне нужно повторять это десятки раз, я ищу способ автоматизировать этот процесс. Было бы замечательно иметь функцию , которой мне просто нужно передать (а) имена группирующих переменных (например, пол, образование) и (б) переменные, из которых можно получить M / SD (например, var1, var2).

Решение, которое я ищу, должно выглядеть так (статистика неверна в приведенном ниже примере):

my_results <- tibble(grouping_vars = c("place_London","place_Paris","place_Rome","place_Madrid","gender_m","gender_f","last_element"),mean_var1=c(1.3,2.5,4.5,1.7,2.5,3.6,4.0),sd_var1=c(0.01,0.41,0.21,0.12,0.02,0.38,0.28),mean_var2=c(4.3,4.5,4.0,1.2,2.5,1.6,2.3),sd_var2=c(0.21,0.1,0.1,0.32,0.22,0.18,0.08),mean_var3=c(2.3,2.5,2.0,3.2,3.5,0.6,5),sd_var3=c(0.51,0.15,0.51,0.52,0.52,0.15,0.48))

  grouping_vars  mean_var1 sd_var1 mean_var2 sd_var2 mean_var3 sd_var3
  <chr>              <dbl>   <dbl>     <dbl>   <dbl>     <dbl>   <dbl>
1 place_London         1.3    0.01       4.3    0.21       2.3    0.51
2 place_Paris          2.5    0.41       4.5    0.1        2.5    0.15
3 place_Rome           4.5    0.21       4      0.1        2      0.51
4 place_Madrid         1.7    0.12       1.2    0.32       3.2    0.52
5 gender_m             2.5    0.02       2.5    0.22       3.5    0.52
6 gender_f             3.6    0.38       1.6    0.18       0.6    0.15
7 last_element         4      0.28       2.3    0.08       5      0.48

Поскольку я обычно работаю с tidyverse , Я был бы особенно признателен за решения, в которых используются эти пакеты (возможно, dplyr или purrr?).

EDIT:

Я подумал, что есть элегантный способ сделать это с помощью map (). Может быть, но я еще не нашел. А пока я придумал способ, который просто реструктурирует данные в соответствующий длинный формат, а затем вычисляет статистику.

df %>% 
  # all grouping vars need to be of the same type, here "factor" is most appropriate
  mutate_at(grouping_vars, list(factor)) %>%
  # pivot longer, so that each row is a unique combination of grouping variable and grouping level
  pivot_longer(
    cols = one_of(grouping_vars), 
    names_to = "group_var",
    values_to = "group_level"
  ) %>% 
  # merge grouping variable and group level into a single column 
  unite(var_level,group_var,group_level, sep="_") %>% 
  # group by group level
  group_by(var_level) %>% 
  # compute means and sd for each test variable
  summarise_at(test_vars,  list(~mean(., na.rm = TRUE), ~sd(., na.rm = TRUE)))

Результат кажется прекрасным, например, среднее значение var1 двух людей кто живет в Лондоне (2,2 + 4,5) - 3,35.

# A tibble: 10 x 7
   var_level    var1_mean var2_mean var3_mean var1_sd var2_sd var3_sd
   <chr>            <dbl>     <dbl>     <dbl>   <dbl>   <dbl>   <dbl>
 1 education_1       2.65      3.15      0.15   0.636   1.48   0.0707
 2 education_2       4.5       2.5       3.5   NA      NA     NA     
 3 education_3       1.65      2.65      3.65   0.919   1.91   0.919 
 4 education_5       3.2       4.7       3.7    2.55    0.424  1.84  
 5 gender_f          2.72      2.48      2.72   1.47    1.13   1.83  
 6 gender_m          2.87      4.53      2.53   1.89    0.416  2.40  
 7 place_London      3.35      3.35      1.85   1.63    1.20   2.33  
 8 place_Madrid      1.85      2.85      3.35   0.636   2.19   1.34  
 9 place_Paris       3.1       2.1       0.1   NA      NA     NA     
10 place_Rome        3         4.5       4      2.83    0.707  1.41  

Есть ли какие-либо мысли о возможных рисках этого подхода или о том, как его можно улучшить?

1 Ответ

3 голосов
/ 28 мая 2020

Один из вариантов - функция describeBy из psych:

library(psych)
describeBy(df,group = c("gender","education"), mat= TRUE)

Затем подмножество того, что вы хотите оттуда.


Другой, удивительно простой вариант с dplyr:

library(dplyr)
group.vars <- c("gender","education")
measure.vars <- c("var1","var2")

df %>% 
  group_by_at(group.vars) %>%
  summarize_at(measure.vars,
                      list(mean =~ mean(.),sd =~ sd(.)))
# A tibble: 5 x 6
# Groups:   gender [2]
  gender education var1_mean var2_mean var1_sd var2_sd
  <chr>      <dbl>     <dbl>     <dbl>   <dbl>   <dbl>
1 f              1      3.1       2.1   NA      NA    
2 f              2      4.5       2.5   NA      NA    
3 f              3      1.65      2.65   0.919   1.91 
4 m              1      2.2       4.2   NA      NA    
5 m              5      3.2       4.7    2.55    0.424

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

...