problemy z dplyr podczas używania group by(wiele zmiennych)

Chcę zacząć używać dplyr zamiast ddply, ale nie mogę zrozumieć, jak to działa (przeczytałem dokumentację).

Na przykład, dlaczego gdy próbuję zmutować () coś nie działa tak jak powinno?

Patrząc na mtcars:

Biblioteka (samochód)

Powiedzmy, że robię dane.rama będąca podsumowaniem mtcars, pogrupowanych według " cyl " i "gear":
df1 <- mtcars %.%
            group_by(cyl, gear) %.%
            summarise(
                newvar = sum(wt)
            )

Następnie powiedz, że chcę dalej podsumować tę ramkę danych. Z ddply byłoby proste, ale kiedy próbuję zrobić z dplyr, to nie jest tak naprawdę "grupowanie przez": {]}

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

Nadal daje niezgrupowane wyjście:

  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

Czy robię coś nie tak ze składnią?


Edit:

Gdybym to zrobił z plyr i ddply:

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

A następnie uzyskać drugie df:

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

Ale to samo podejście, z sum (newvar) + 5 w funkcji summary () nie działa z dplyr...

Author: smci, 2014-02-09

5 answers

Biorąc odpowiedź Dicoa krok dalej -- jak mówi Hadley "summary złuszcza jedną warstwę grupowania". Odrywa się od odwrotnej kolejności, w jakiej został zastosowany, dzięki czemu można po prostu użyć

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

Zwróć uwagę, że to da inną odpowiedź, jeśli użyjesz group_by(gear, cyl) w drugiej linii.

I aby pierwsza próba zadziałała:

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

df2 <- df1 %>%
 group_by(cyl) %>%
 summarise(newvar2 = sum(newvar)+5)
 35
Author: Tim Cameron,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-11-28 22:07:40

Miałem podobny problem. Znalazłem, że po prostu odłączenie plyr rozwiązało to:

detach(package:plyr)    
library(dplyr)
 61
Author: ManneR,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-09-08 19:29:34

Jeśli przetłumaczysz swój kod plyr na dplyr używając summarise zamiast mutate, uzyskasz takie same wyniki.

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

Ponieważ summarise zrzuca ostatnią grupę (gear) możesz pominąć drugą group_by (Zobacz komentarz @hadley poniżej)

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
 10
Author: dickoa,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-02-09 21:28:48

Odłączanie plyr jest jednym ze sposobów rozwiązania problemu, dzięki czemu można używać funkcji dplyr zgodnie z potrzebami... ale co, jeśli potrzebujesz innych funkcji z plyr, aby wykonać inne zadania w kodzie?

(w tym przykładzie mam załadowane biblioteki dplyr i plyr)

Załóżmy, że mamy proste dane.ramki i chcemy obliczyć sumę groupwise zmiennej value, gdy zgrupowane są według różnych poziomów 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

Ale kiedy spróbujemy użyć tego, co wierzymy, będzie produkować dplyr suma zespolona, oto co się dzieje:

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

To nie daje nam pożądanej odpowiedzi. Prawdopodobnie z powodu jakiejś interakcji lub przeciążenia funkcji group_by I or mutate pomiędzy dplyr i plyr. Możemy odłączyć plyr, ale innym sposobem jest podanie unikalnego wywołania do dplyr wersji group_by i 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

Teraz widzimy, że to działa zgodnie z oczekiwaniami.

 5
Author: Brett Borghetti,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-02-27 02:14:41

Dplyr działa tak, jak powinieneś się spodziewać w swoim przykładzie. Mutate, jak go określiłeś, po prostu doda 5 do każdej wartości newvar podczas tworzenia newvar2. To będzie wyglądać tak samo, jeśli grupa lub nie. Jeśli jednak podasz coś, co różni się od grupy, otrzymasz coś innego. Na przykład:

df1 %.%
            group_by(cyl) %.%
            mutate(
                newvar2 = newvar + mean(cyl)
            )
 4
Author: Vincent,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-02-09 00:16:31