Как подвести итоги по группам И получить сводку общего набора данных, используя dplyr в R - PullRequest
1 голос
/ 11 ноября 2019

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

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

Воспроизводимые данные:

library(tidyverse)
set.seed(500)
dat <- 
    data_frame(treatment = sample(c("Group1", "Group2", "Group3"), 100, replace = TRUE),
               recruitment_strategy = sample(c("Strategy 1", "Strategy 2", "Strategy 3", "Strategy 4", "Strategy 5"), 100, replace = TRUE),
               Variable_A = rnorm(100),
               Variable_B = rnorm(100),
               Variable_C = rnorm(100))

Код для вычисления средних значений нескольких переменных по группе И средних значений изобщий набор данных:

count_by_group <- dat %>% 
    group_by(treatment) %>% 
    count(recruitment_strategy) %>%
    mutate(`n (%)` = paste0(n, " (", round(n / sum(n)*100,0), "%)")) %>%
    select(-n) %>%
    spread(treatment, `n (%)`)

count_overall <- dat %>% 
    count(recruitment_strategy) %>%
    mutate(`n (%)` = paste0(n, " (", round(n / sum(n)*100,0), "%)")) %>%
    select(-n) %>%
    rename(Overall_dataset = `n (%)`)

left_join(count_by_group, count_overall)

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

  variable   Group1  Group2  Group3 Overall_dataset
  <chr>       <dbl>   <dbl>   <dbl>           <dbl>
1 Variable_A -0.154  0.0385  0.263           0.0351
2 Variable_B  0.212 -0.232  -0.124          -0.0671
3 Variable_C -0.195  0.194   0.0508          0.0376

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

count_by_group <- dat %>% 
    group_by(treatment) %>% 
    count(recruitment_strategy) %>%
    mutate(`n (%)` = paste0(n, " (", round(n / sum(n)*100,0), "%)")) %>% # calculate percentage in the desired format for table
    select(-n) %>%
    spread(treatment, `n (%)`)

count_overall <- dat %>% 
    count(recruitment_strategy) %>%
    mutate(`n (%)` = paste0(n, " (", round(n / sum(n)*100,0), "%)")) %>% # calculate percentage in the desired format for table
    select(-n) %>%
    rename(Overall_dataset = `n (%)`)

left_join(count_by_group, count_overall)

  recruitment_strategy Group1  Group2   Group3  Overall_dataset
  <chr>                <chr>   <chr>    <chr>   <chr>          
1 Strategy 1           2 (6%)  13 (30%) 4 (16%) 19 (19%)       
2 Strategy 2           8 (26%) 6 (14%)  6 (24%) 20 (20%)       
3 Strategy 3           6 (19%) 12 (27%) 3 (12%) 21 (21%)       
4 Strategy 4           9 (29%) 4 (9%)   5 (20%) 18 (18%)       
5 Strategy 5           6 (19%) 9 (20%)  7 (28%) 22 (22%) 

Существует ли решение, которое может получить групповое резюме и общее резюме за один шаг, вместоназначение двух отдельных объектов, которые затем объединяются в третий объект?

1 Ответ

1 голос
/ 11 ноября 2019

Вот как я бы переписал ваш код.

Существует хитрость с использованием труб, чтобы использовать . для размещения LHS в нескольких местах на RHS. Это позволяет вам выполнять объединение без необходимости назначения промежуточных объектов. Я также использовал еще несколько шагов для достижения другого баланса ясности и отсутствия повторения, например, выполнить всю группировку внутри count() и использовать ее аргумент name, использовать mutate_at, чтобы выполнить все форматирование после объединения, ииспользуя str_glue и scales::percent, чтобы сделать форматирование строки немного более читабельным.

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

library(tidyverse)
set.seed(500)
dat <- tibble(
  treatment = sample(c("Group1", "Group2", "Group3"), 100, replace = TRUE),
  recruitment_strategy = sample(c("Strategy 1", "Strategy 2", "Strategy 3", "Strategy 4", "Strategy 5"), 100, replace = TRUE),
  Variable_A = rnorm(100),
  Variable_B = rnorm(100),
  Variable_C = rnorm(100)
)

dat %>%
  inner_join(
      x = count(., treatment, recruitment_strategy) %>% spread(treatment, n),
      y = count(., recruitment_strategy, name = "Overall_dataset"),
      by = "recruitment_strategy"
  ) %>%
  mutate_at(
    .vars = vars(-recruitment_strategy),
    .funs = ~ str_glue("{.} ({scales::percent(. / sum(.), accuracy = 1)})")
  )
#> # A tibble: 5 x 5
#>   recruitment_strategy Group1  Group2   Group3  Overall_dataset
#>   <chr>                <glue>  <glue>   <glue>  <glue>         
#> 1 Strategy 1           2 (6%)  13 (30%) 4 (16%) 19 (19%)       
#> 2 Strategy 2           8 (26%) 6 (14%)  6 (24%) 20 (20%)       
#> 3 Strategy 3           6 (19%) 12 (27%) 3 (12%) 21 (21%)       
#> 4 Strategy 4           9 (29%) 4 (9%)   5 (20%) 18 (18%)       
#> 5 Strategy 5           6 (19%) 9 (20%)  7 (28%) 22 (22%)

Создан в 2019-11-10 пакетом Представить (v0.3.0)

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