dplyr суммировать: Эквивалент «.drop = FALSE» для сохранения групп с нулевой длиной в выходе

При использовании summarise с plyr ddply пустые категории по умолчанию отбрасываются. Вы можете изменить это поведение, добавив .drop = FALSE . Однако это не работает при использовании summarise с dplyr . Есть ли другой способ сохранить пустые категории в результате?

Вот пример с поддельными данными.

 library(dplyr) df = data.frame(a=rep(1:3,4), b=rep(1:2,6)) # Now add an extra level to df$b that has no corresponding value in df$a df$b = factor(df$b, levels=1:3) # Summarise with plyr, keeping categories with a count of zero plyr::ddply(df, "b", summarise, count_a=length(a), .drop=FALSE) b count_a 1 1 6 2 2 6 3 3 0 # Now try it with dplyr df %.% group_by(b) %.% summarise(count_a=length(a), .drop=FALSE) b count_a .drop 1 1 6 FALSE 2 2 6 FALSE 

Не совсем то, на что я надеялся. Есть ли метод dplyr для достижения того же результата, что и .drop=FALSE в plyr ?

Проблема по-прежнему открыта, но тем временем, тем более, что ваши данные уже учтены, вы можете использовать complete от «tidyr», чтобы получить то, что вы можете искать:

 library(tidyr) df %>% group_by(b) %>% summarise(count_a=length(a)) %>% complete(b) # Source: local data frame [3 x 2] # # b count_a # (fctr) (int) # 1 1 6 # 2 2 6 # 3 3 NA 

Если вы хотите, чтобы значение замены было равно нулю, вам нужно указать, что при fill :

 df %>% group_by(b) %>% summarise(count_a=length(a)) %>% complete(b, fill = list(count_a = 0)) # Source: local data frame [3 x 2] # # b count_a # (fctr) (dbl) # 1 1 6 # 2 2 6 # 3 3 0 

Решение dplyr:

Сначала сгруппируйте df

 by_b <- tbl_df(df) %>% group_by(b) 

то мы суммируем те уровни, которые происходят путем подсчета с n()

 res <- by_b %>% summarise( count_a = n() ) 

то мы объединяем наши результаты в кадр данных, который содержит все уровни факторов:

 expanded_res <- left_join(expand.grid(b = levels(df$b)),res) 

наконец, в этом случае, поскольку мы смотрим на подсчеты, значения NA меняются на 0.

 final_counts <- expanded_res[is.na(expanded_res)] <- 0 

Это также можно реализовать функционально, см. Ответы: Добавить строки в сгруппированные данные с помощью dplyr?

Взлом:

Я думал, что я опубликую ужасный хак, который работает в этом случае ради интереса. Я серьезно сомневаюсь, что вы действительно должны это делать, но это показывает, как group_by() генерирует атрибуты, как если бы df$b был символьным вектором, а не фактором с уровнями. Кроме того, я не претендую на это правильно, но я надеюсь, что это поможет мне учиться - это единственная причина, по которой я отправляю его!

 by_b <- tbl_df(df) %>% group_by(b) 

определите значение «вне пределов», которое не может существовать в наборе данных.

 oob_val <- nrow(by_b)+1 

изменить атрибуты на «трюк» summarise() :

 attr(by_b, "indices")[[3]] <- rep(NA,oob_val) attr(by_b, "group_sizes")[3] <- 0 attr(by_b, "labels")[3,] <- 3 

сделать резюме:

 res <- by_b %>% summarise(count_a = n()) 

индексировать и заменять все вхождения oob_val

 res[res == oob_val] <- 0 

который дает предполагаемое:

 > res Source: local data frame [3 x 2] b count_a 1 1 6 2 2 6 3 3 0 

это не совсем то, что было задано в вопросе, но, по крайней мере, для этого простого примера, вы можете получить тот же результат, используя xtabs, например:

используя dplyr:

 df %.% xtabs(formula = ~ b) %.% as.data.frame() 

или короче:

 as.data.frame(xtabs( ~ b, df)) 

результат (равный в обоих случаях):

  b Freq 1 1 6 2 2 6 3 3 0 
  • Ошибка: не удалось найти функцию ... в R
  • Заказ баров в ggplot
  • Укажите пользовательский формат даты для аргумента colClasses в read.table / read.csv
  • График временных рядов смещается на 2 часа, если используется scale_x_datetime
  • Загружать сразу несколько пакетов
  • Булевы операторы && и ||
  • Подмножество по группам с data.table
  • Как отображать частоту в верхней части каждого фактора в штриховом шрифте в R
  • Удалите пространство между полосками ggplot2
  • как кумулятивно добавить значения в один вектор из R
  • Как создать ряд наиболее отличительных цветов в R?
  • Давайте будем гением компьютера.