195 votes

Agréger / résumer plusieurs variables par groupe (par exemple, somme, moyenne)

À partir d'un cadre de données, existe-t-il un moyen simple d'agréger ( sum , mean , max et c) plusieurs variables simultanément ?

Vous trouverez ci-dessous quelques exemples de données :

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)

Je voudrais agréger simultanément les x1 y x2 des variables de l df2 cadre de données par année et par mois. Le code suivant permet d'agréger les x1 mais est-il également possible d'agréger simultanément la variable x2 variable ?

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

211voto

Andrie Points 66979

Oui, dans votre formula vous pouvez cbind les variables numériques à agréger :

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

Ver ?aggregate El formula l'argument et les exemples.

66voto

Jaap Points 3814

Avec le dplyr vous pouvez utiliser summarise_all , summarise_at o summarise_if pour agréger plusieurs variables simultanément. Pour l'ensemble de données de l'exemple, vous pouvez procéder comme suit :

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 using select_helpers
# see ?select_helpers for more options
df2 <- df1 %>% group_by(year, month) %>% summarise_at(vars(starts_with('x')), sum)
df2 <- df1 %>% group_by(year, month) %>% summarise_at(vars(matches('.*[0-9]')), sum)

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

Le résultat de ces deux dernières options :

    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

Note : summarise_each est déprécié au profit de summarise_all , summarise_at y summarise_if .


Comme mentionné dans mon commentaire ci-dessus vous pouvez également utiliser l'option recast de la fonction reshape2 -package :

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

ce qui vous donnera le même résultat.

58voto

numbercruncher Points 864

Utilisation de la data.table qui est rapide (utile pour les grands ensembles de données).

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

Utilisation du paquet plyr

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

Utilisation de summarize() du paquet Hmisc (les titres des colonnes sont désordonnés dans mon exemple)

# 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))

48voto

EDi Points 6038

Où se trouve cette year() de la fonction ?

Vous pouvez également utiliser le reshape2 pour cette tâche :

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

23voto

Jozef Points 1563

Il est intéressant de noter que la base R aggregate 's data.frame n'est pas mise en valeur ici, au-dessus de l'interface de la formule est utilisée, donc par souci d'exhaustivité :

aggregate(
  x = df1[c("x1", "x2")],
  by = df1[c("year", "month")],
  FUN = sum, na.rm = TRUE
)

Utilisation plus générique de la méthode data.frame de l'agrégat :

Puisque nous fournissons un

  • data.frame comme x y
  • a list ( data.frame est également un list ) comme by Ceci est très utile si nous avons besoin de l'utiliser de manière dynamique, par exemple en utilisant d'autres colonnes pour être agrégées et pour agréger par est très simple.
  • également avec des fonctions d'agrégation sur mesure

Par exemple, comme ceci :

colsToAggregate <- c("x1")
aggregateBy <- c("year", "month")
dummyaggfun <- function(v, na.rm = TRUE) {
  c(sum = sum(v, na.rm = na.rm), mean = mean(v, na.rm = na.rm))
}

aggregate(df1[colsToAggregate], by = df1[aggregateBy], FUN = dummyaggfun)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X