437 votes

Comment grouper des colonnes en somme dans la R

Disons que j'ai deux colonnes de données. La première contient les catégories telles que "Première", "Deuxième", "Troisième", etc. La deuxième a des nombres qui représentent le nombre de fois que j'ai vu "la Première".

Par exemple:

Category     Frequency
First        10
First        15
First        5
Second       2
Third        14
Third        20
Second       3

Je veux trier les données par Catégorie et ajoutez les Fréquences:

Category     Frequency
First        30
Second       5
Third        34

Comment pourrais-je le faire dans la R? J'ai regardé le tri et fonctions d'ordre, mais je ne sais pas comment faire la somme des Fréquences avec les Catégories.

465voto

rcs Points 22112

À l'aide de aggregate:

x <- data.frame(Category=factor(c("First", "First", "First", "Second",
                                  "Third", "Third", "Second")), 
                Frequency=c(10,15,5,2,14,20,3))
aggregate(x$Frequency, by=list(Category=x$Category), FUN=sum)
  Category  x
1    First 30
2   Second  5
3    Third 34

ou tapply:

tapply(x$Frequency, x$Category, FUN=sum)
 First Second  Third 
    30      5     34

81voto

asieira Points 400

La réponse fournie par rcs fonctionne et est simple. Toutefois, si vous êtes à la manipulation des plus grands ensembles de données et ont besoin d'un boost de performance il y a une meilleure solution:

> library(data.table)
> data = data.table(Category=c("First", "First", "First", "Second", "Third", "Third",   "Second"), Frequency=c(10,15,5,2,14,20,3))
> data[,sum(Frequency),by=Category]
   Category V1
1:    First 30
2:   Second  5
3:    Third 34
> system.time( data[,sum(Frequency),by=Category] )
     user    system   elapsed 
    0.008     0.001     0.009 

Nous allons les comparer à la même chose en utilisant des données.image ci-dessus:

> data = data.frame(Category=c("First", "First", "First", "Second", "Third", "Third", "Second"), Frequency=c(10,15,5,2,14,20,3))
> system.time( aggregate(data$Frequency, by=list(Category=data$Category), FUN=sum) )
     user    system   elapsed 
    0.008     0.000     0.015 

Et si vous voulez garder la colonne c'est la syntaxe:

> data[,list(Frequency=sum(Frequency)),by=Category]
   Category Frequency
1:    First        30
2:   Second         5
3:    Third        34

La différence sera plus perceptible avec les plus grands ensembles de données, comme le code ci-dessous montre:

> data = data.table(Category=rep(c("First", "Second", "Third"), 100000), Frequency=rnorm(100000))
> system.time( data[,sum(Frequency),by=Category] )
     user    system   elapsed 
    0.055     0.004     0.059 
> data = data.frame(Category=rep(c("First", "Second", "Third"), 100000), Frequency=rnorm(100000))
> system.time( aggregate(data$Frequency, by=list(Category=data$Category), FUN=sum) )
     user    system   elapsed 
    0.287     0.010     0.296 

43voto

Shane Points 40885

C'est un peu liée à cette question.

Vous pouvez aussi simplement utiliser des le par() fonction:

x2 <- by(x$Frequency, x$Category, sum)
do.call(rbind,as.list(x2))

D'autres paquets (plyr, remodeler), bénéficient de la restitution de données.cadre, mais il vaut la peine d'être familier avec par() puisque c'est une fonction de base.

29voto

learnr Points 1585
library(plyr)
ddply(tbl, .(Category), summarise, sum = sum(Frequency))

20voto

dalloliogm Points 2628

Juste pour ajouter une troisième option:

require(doBy)
summaryBy(Frequency~Category, data=yourdataframe, FUN=sum)

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