Подтвердить что ты не робот

Проблемы dplyr при использовании group_by (несколько переменных)

Я хочу начать использовать dplyr вместо ddply, но я не могу понять, как это работает (я прочитал документацию).

Например, почему, когда я пытаюсь выполнить mutate(), функция "group_by" не работает так, как она должна была?

Глядя на mtcars:

библиотека (автомобиль)

Скажем, я делаю data.frame, который представляет собой сводку mtcars, сгруппированных по "cyl" и "gear":

df1 <- mtcars %.%
            group_by(cyl, gear) %.%
            summarise(
                newvar = sum(wt)
            )

Затем скажите, что я хочу еще раз обобщить этот файл данных. С ddply это было бы просто, но когда я пытаюсь сделать это с dplyr, это не на самом деле "группировка":

df2 <- df1 %.%
            group_by(cyl) %.%
            mutate(
                newvar2 = newvar + 5
            )

По-прежнему выводится негруппированный вывод:

  cyl gear newvar newvar2
1   6    3  6.675  11.675
2   4    4 19.025  24.025
3   6    4 12.375  17.375
4   6    5  2.770   7.770
5   4    3  2.465   7.465
6   8    3 49.249  54.249
7   4    5  3.653   8.653
8   8    5  6.740  11.740

Я что-то не так с синтаксисом?


Edit:

Если бы я сделал это с помощью plyr и ddply:

df1 <- ddply(mtcars, .(cyl, gear), summarise, newvar = sum(wt))

а затем для получения второго df:

df2 <- ddply(df1, .(cyl), summarise, newvar2 = sum(newvar) + 5)

Но этот же подход с суммой (newvar) + 5 в функции summary() не работает с dplyr...

4b9b3361

Ответ 1

Взяв Дикоа, ответьте на один шаг дальше - как говорит Хэдли, "суммировать отслаивание с одного слоя группировки". Он удаляет группировку из обратного порядка, в который вы ее применили, поэтому вы можете просто использовать

mtcars %>%
 group_by(cyl, gear) %>%
 summarise(newvar = sum(wt)) %>%
 summarise(newvar2 = sum(newvar) + 5)

Обратите внимание, что это даст другой ответ, если вы используете group_by(gear, cyl) во второй строке.

И чтобы ваша первая попытка работала:

df1 <- mtcars %>%
 group_by(cyl, gear) %>%
 summarise(newvar = sum(wt))

df2 <- df1 %>%
 group_by(cyl) %>%
 summarise(newvar2 = sum(newvar)+5)

Ответ 2

У меня была аналогичная проблема. Я обнаружил, что просто отсоединение plyr решило его:

detach(package:plyr)    
library(dplyr)

Ответ 3

Если вы переведете код plyr в dplyr, используя summarise вместо mutate, вы получите те же результаты.

library(plyr)
df1 <- ddply(mtcars, .(cyl, gear), summarise, newvar = sum(wt))
df2 <- ddply(df1, .(cyl), summarise, newvar2 = sum(newvar) + 5)
df2
##   cyl newvar2
## 1   4  30.143
## 2   6  26.820
## 3   8  60.989

detach(package:plyr)    
library(dplyr)
mtcars %.%
    group_by(cyl, gear) %.%
    summarise(newvar = sum(wt)) %.%
    group_by(cyl) %.%
    summarise(newvar2 = sum(newvar) + 5)
##   cyl newvar2
## 1   4  30.143
## 2   8  60.989
## 3   6  26.820

EDIT

Так как summarise отбрасывает последнюю группу (gear), вы можете пропустить второй group_by (см. комментарий @hadley ниже)

library(dplyr)
mtcars %.%
    group_by(cyl, gear) %.%
    summarise(newvar = sum(wt)) %.%
    summarise(newvar2 = sum(newvar) + 5)
##   cyl newvar2
## 1   4  30.143
## 2   8  60.989
## 3   6  26.820

Ответ 4

Отключение plyr - один из способов решения проблемы, поэтому вы можете использовать функции dplyr по желанию... но что, если вам нужны другие функции из plyr для выполнения других задач в вашем коде?

(В этом примере у меня загружены библиотеки dplyr и plyr)

Предположим, что у нас есть простой data.frame, и мы хотим вычислить групповую сумму переменной value, если сгруппировать по разным уровням gname

> dx<-data.frame(gname=c(1,1,1,2,2,2,3,3,3), value = c(2,2,2,4,4,4,5,6,7))
> dx
  gname value
1     1     2
2     1     2
3     1     2
4     2     4
5     2     4
6     2     4
7     3     5
8     3     6
9     3     7

Но когда мы пытаемся использовать то, что, по нашему мнению, создадим сгруппированную сумму dplyr, вот что происходит:

dx %>% group_by(gname) %>% mutate(mysum=sum(value))
Source: local data frame [9 x 3]
Groups: gname

  gname value mysum
1     1     2    36
2     1     2    36
3     1     2    36
4     2     4    36
5     2     4    36
6     2     4    36
7     3     5    36
8     3     6    36
9     3     7    36

Это не дает нам желаемого ответа. Вероятно, из-за некоторого взаимодействия или перегрузки функций group_by и или mutate между dplyr и plyr. Мы могли бы отсоединить plyr, но другой способ - дать уникальный вызов dplyr версиям group_by и mutate:

dx %>% dplyr::group_by(gname) %>% dplyr::mutate(mysum=sum(value))
Source: local data frame [9 x 3]
Groups: gname

  gname value mysum
1     1     2     6
2     1     2     6
3     1     2     6
4     2     4    12
5     2     4    12
6     2     4    12
7     3     5    18
8     3     6    18
9     3     7    18

теперь мы видим, что это работает как ожидалось.

Ответ 5

dplyr работает так, как вам следует ожидать в вашем примере. Mutate, как вы указали, просто добавит 5 к каждому значению newvar, поскольку он создает newvar2. Это будет выглядеть одинаково, если вы группируете или нет. Если, однако, вы указываете что-то, что отличается по группе, вы получите что-то другое. Например:

df1 %.%
            group_by(cyl) %.%
            mutate(
                newvar2 = newvar + mean(cyl)
            )