Dplyr: суммирование одновременно для групп и целых данных - PullRequest
1 голос
/ 08 мая 2020

Я вычисляю сводные статистики для многих переменных в большом фрейме данных (он имеет 130 переменных). Я использую sh для вычисления сводной статистики за десятилетие и для всех моих данных. Я бы не хотел писать резюме дважды: один раз для группировки и один раз для полных данных. Я также использую summarise_at, поэтому мой вопрос также относится к summarise_at.

Вот минимальный пример, где summarise_at () кажется немного чрезмерным, но не так для моих реальных данных:

my.data <- data.frame(Date = as.Date(c('1981-04-09', '1983-02-01', '1992-10-19', '1996-11-22', '1987-05-15')),
  decade = c('Eighties', 'Eighties', 'Nineties', 'Nineties', 'Eighties'),
  price = c(10, 11, 17, 34, 12),
  d.sector.Oil = c(0,0,1,1,1),
  d.sector.Mines = c(1,1,0,0,0)) # An example dataframe
# Calculate summary statistics for each decade and each variable:
sumst.decades<- my.data %>% group_by(decade) %>% summarise(mean.price = mean(price))
sumd.decades<- my.data %>% group_by(decade) %>% summarise_at(vars(starts_with('d.sector.')), sum)

Мне нужны те же сводки для моих полных данных. Для этого я бы повторил приведенные выше командные строки, но без "group_by":

sumst<- summarise(my.data, mean.price = mean(price))
sumd<- summarise_at(my.data, vars(starts_with('d.sector.')), sum)

I wi sh, чтобы не писать последние две строки, но каким-то образом dplyr дал мне глобальную сводку в дополнение к групповым сводкам. Например, если есть функция group_by *, которая создает группы по мере необходимости, а также создает глобальную группу. Что-то подобное существует? Надеюсь, мой вопрос ясен. Заранее спасибо.

Ответы [ 2 ]

2 голосов
/ 08 мая 2020

Решение Tidyverse:

library(tidyverse)

my.data %>% 
  mutate(decade = as.character(decade)) %>%
  bind_rows(., my.data %>% mutate(decade = as.character("All"))) %>%
  group_by(decade) %>% 
  summarise_if(is.numeric, c("sum", "mean")) %>% 
  ungroup()
1 голос
/ 08 мая 2020

Мне неизвестна существующая функция dplyr, которая делает это. Но я написал обходную функцию, которую вы можете использовать для этой цели:

overall_group = function(data, col_name){

  d1 = data %>%
    mutate(summary_level = "grouped")

  d2 = data %>%
    mutate(summary_level = "ungrouped") %>%
    mutate(!!sym(col_name) := NA)

  d12 = rbind(d1, d2) %>%
    group_by(summary_level, !!sym(col_name))

  return(d12)
}

Демонстрация:

> mtcars %>% summarise(avg_mpg = mean(mpg))
   avg_mpg
1 20.09062
> mtcars %>% group_by(gear) %>% summarise(avg_mpg = mean(mpg))
# A tibble: 3 x 2
   gear avg_mpg
  <dbl>   <dbl>
1     3    16.1
2     4    24.5
3     5    21.4
> mtcars %>% overall_group("gear") %>% summarise(avg_mpg = mean(mpg))
# A tibble: 4 x 3
# Groups:   summary_level [2]
  summary_level  gear avg_mpg
  <chr>         <dbl>   <dbl>
1 grouped           3    16.1
2 grouped           4    24.5
3 grouped           5    21.4
4 ungrouped        NA    20.1

Этот подход представляет собой взлом group_by. Было бы лучше реализовать функциональность overall_* в суммировании. Однако я недостаточно знаю о внутренней работе суммирования, чтобы разработать такую ​​функцию.

Альтернатива: наличие строки, которая дает общее или общее среднее значение, более распространено при представлении таблиц для отчетов. Так что вам может быть лучше поискать такую ​​сводную функцию в пакете, который фокусируется на представлении таблиц, вместо использования dplyr.

...