Проблемы 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...
Ответы
Ответ 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)
)