2012-03-15 13 views
99

Czy z ramki danych można w prosty sposób agregować jednocześnie (tzn. Sumować) wiele zmiennych?Agregacja/podsumowanie wielu zmiennych na grupę (tj. Suma, średnia itp.)

Oto niektóre przykładowe dane:

library(lubridate) 
days = 365*2 
date = seq(as.Date("2000-01-01"), length = days, by = "day") 
year = year(date) 
month = month(date) 
x1 = cumsum(rnorm(days, 0.05)) 
x2 = cumsum(rnorm(days, 0.05)) 
df1 = data.frame(date, year, month, x1, x2) 

Chciałbym jednocześnie agregują x1 i x2 zmienne z ramą df2 danych przez rok i miesiąc. Poniższy kod agreguje zmienną x1, ale czy jest możliwe jednoczesne agregowanie zmiennej x2?

### aggregate variables by year month 
df2=aggregate(x1 ~ year+month, data=df1, sum, na.rm=TRUE) 
head(df2) 

Wszelkie sugestie będą mile widziane.

+0

@Jaap To pytanie nie jest duplikatem z poniższym linkiem. Dzieje się tak dlatego, że chodzi o to, co zrobić z "dplyr". Anuluj zduplikowany znak. r - Podsumowując wiele kolumn z dplyr? - Przepełnienie stosu https://stackoverflow.com/questions/21644848/summarizing-multiple-columns-with-dplyr – Keiku

Odpowiedz

32

Skąd pochodzi funkcja roku()?

Można również skorzystać z pakietu reshape2 dla tego zadania:

require(reshape2) 
df_melt <- melt(df1, id = c("date", "year", "month")) 
dcast(df_melt, year + month ~ variable, sum) 
# year month   x1   x2 
1 2000  1 -80.83405 -224.9540159 
2 2000  2 -223.76331 -288.2418017 
3 2000  3 -188.83930 -481.5601913 
4 2000  4 -197.47797 -473.7137420 
5 2000  5 -259.07928 -372.4563522 
+6

Funkcja 'recast' (także z' reshape2') integruje funkcję 'stopu' i' dcast' za jednym razem w przypadku takich zadań: 'przekształcenie (df1, rok + miesiąc ~ zmienna, suma, id.var = c ("date", "year", "month")) " – Jaap

151

Tak, w swoim formula można cbind zmiennych numerycznych należy agregować:

aggregate(cbind(x1, x2) ~ year + month, data = df1, sum, na.rm = TRUE) 
    year month   x1   x2 
1 2000  1 7.862002 -7.469298 
2 2001  1 276.758209 474.384252 
3 2000  2 13.122369 -128.122613 
... 
23 2000 12 63.436507 449.794454 
24 2001 12 999.472226 922.726589 

Zobacz ?aggregate, z formula argumentów i przykładów.

+2

Czy jest możliwe, aby cbind używał zmiennych dynamicznych? –

+9

Warto zauważyć, że gdy dowolna zmienna, która jest w cbind ma NA, wiersz zostanie usunięty dla każdej zmiennej w cbind. Nie takie zachowanie oczekiwałem. –

+0

co jeśli zamiast x1 i x2 chcę używać wszystkich pozostałych zmiennych (innych niż rok, miesiąc) –

39

Korzystanie pakiet data.table, który jest szybki (przydatne w przypadku większych zbiorów danych)

https://github.com/Rdatatable/data.table/wiki

library(data.table) 
df2 <- setDT(df1)[, lapply(.SD, sum), by=.(year, month), .SDcols=c("x1","x2")] 
setDF(df2) # convert back to dataframe 

Używanie Pakiet plyr

require(plyr) 
df2 <- ddply(df1, c("year", "month"), function(x) colSums(x[c("x1", "x2")])) 

Korzystanie podsumować() z pakietu Hmisc (Nagłówki kolumn są bałagan w moim przykładzie chociaż)

# need to detach plyr because plyr and Hmisc both have a summarize() 
detach(package:plyr) 
require(Hmisc) 
df2 <- with(df1, summarize(cbind(x1, x2), by=llist(year, month), FUN=colSums)) 
25

Z pakietem dplyr, można użyć summarise_all, summarise_at lub summarise_if funkcje agregacji wielu zmiennych jednocześnie. Dla przykładu zbiorze można to zrobić w następujący sposób:

library(dplyr) 
# summarising all non-grouping variables 
df2 <- df1 %>% group_by(year, month) %>% summarise_all(sum) 

# summarising a specific set of non-grouping variables 
df2 <- df1 %>% group_by(year, month) %>% summarise_at(vars(x1, x2), sum) 
df2 <- df1 %>% group_by(year, month) %>% summarise_at(vars(-date), sum) 

# summarising a specific set of non-grouping variables based on condition (class) 
df2 <- df1 %>% group_by(year, month) %>% summarise_if(is.numeric, sum) 

Efektem tych dwóch opcji:

year month  x1   x2 
    <dbl> <dbl>  <dbl>  <dbl> 
1 2000  1 -73.58134 -92.78595 
2 2000  2 -57.81334 -152.36983 
3 2000  3 122.68758 153.55243 
4 2000  4 450.24980 285.56374 
5 2000  5 678.37867 384.42888 
6 2000  6 792.68696 530.28694 
7 2000  7 908.58795 452.31222 
8 2000  8 710.69928 719.35225 
9 2000  9 725.06079 914.93687 
10 2000 10 770.60304 863.39337 
# ... with 14 more rows 

Uwaga: summarise_each jest zastąpiona summarise_all, summarise_at i summarise_if.


Jak wspomniano w my comment above, można również użyć funkcji recast z reshape2 -package:

library(reshape2) 
recast(df1, year + month ~ variable, sum, id.var = c("date", "year", "month")) 

która daje ten sam rezultat.

Powiązane problemy