Compter les lignes par groupe : table()
La question de groupement la plus simple est « combien de chaque ? » - et R de base y répond en un seul appel. table() compte la fréquence d'apparition de chaque valeur :
Une colonne donne les effectifs par valeur ; deux colonnes donnent un tableau croisé complet (régions en lignes, formules en colonnes). Pour « quelle proportion ? », enveloppe le tout dans prop.table(table(...)). table() est la route la plus rapide vers une réponse de fréquence dans tout R - ne prends rien de plus lourd quand un simple comptage suffit.
Une statistique par groupe : tapply()
tapply(values, groups, function) découpe le premier vecteur selon le second et applique la fonction à chaque morceau :
Le résultat est un vecteur nommé - étiquettes de groupes en noms, statistiques en valeurs - ce qui le rend parfait pour des consultations rapides (means["EU"]). Le nom se décode comme « table apply » : appliquer une fonction le long d'une table de groupement. Il appartient à la même famille que sapply() et lapply(), traitée dans la doc de la famille apply.
La limite de tapply(), c'est la forme : un vecteur nommé est malcommode à joindre, tracer ou retraiter. Quand le résumé est une étape intermédiaire plutôt que la réponse finale, tu veux récupérer un data frame - ce que renvoie précisément l'outil suivant.
Le cheval de bataille à formule : aggregate()
aggregate() est le group-by complet de R de base : il renvoie un data frame, et son interface formule se lit comme la phrase que tu prononcerais. value ~ group signifie « la valeur, ventilée par groupe » :
Ajouter des variables de groupement revient simplement à écrire + autre_colonne dans la formule - le second appel somme par combinaison région et trimestre. Tu peux aussi agréger plusieurs colonnes de valeurs à la fois avec cbind(a, b) ~ group. Comme la sortie est un data frame ordinaire, elle s'insère directement dans une jointure, un tri ou un graphique - c'est l'outil de base à choisir par défaut pour des résumés groupés.
Un comportement discret à connaître : l'interface formule supprime les lignes contenant un NA dans l'une des colonnes utilisées avant d'agréger. C'est généralement ce que tu veux ; parfois l'explication d'un effectif qui semble bas.
La façon dplyr : group_by() + summarize()
Le standard moderne est le motif à deux verbes de dplyr - group_by() déclare le groupement, summarize() réduit chaque groupe à une ligne, en calculant autant de statistiques que tu en nommes (statique ; le bac à sable n'exécute que du R de base) :
library(dplyr)
sales |>
group_by(region) |>
summarize(
n = n(),
total = sum(amount),
avg = mean(amount)
)
C'est là que dplyr surpasse réellement R de base : plusieurs statistiques par groupe en un appel lisible - aggregate() demande des contorsions pour ça - plus n() gratuitement, et le résultat s'écoule directement dans le pipe suivant. (summarise() est la même fonction, orthographe britannique.)
Une chose qui déroute les nouveaux venus : avec plusieurs variables de groupement, summarize() n'en retire que la dernière, laissant le résultat encore groupé - et affiche un message à ce sujet. Dis explicitement ce que tu veux avec l'argument .groups : summarize(avg = mean(amount), .groups = "drop") renvoie un tableau ordinaire non groupé, ce qui est la bonne habitude par défaut. Un tableau groupé qui se faufile dans le code suivant fait travailler mutate() et compagnie par groupe en silence - source classique de résultats déroutants.
Choisir entre eux
- Un comptage -
table(), rien ne bat un seul appel. - Une statistique, coup d'œil rapide -
tapply(), et lis la réponse sur le vecteur nommé. - Un data frame en sortie, environnement R de base uniquement -
aggregate()avec une formule. - Plusieurs statistiques, dans un pipeline, ou quoi que ce soit d'ambitieux -
group_by() |> summarize().
Il n'y a pas de mauvaise réponse parmi elles - toutes calculent les mêmes nombres - mais adapter l'outil à la forme de sortie dont tu as besoin t'épargne l'étape de conversion. Les moyennes, médianes et dispersions elles-mêmes sont traitées dans les statistiques descriptives.
Exemple traité : mtcars par nombre de cylindres
Tout ensemble sur un jeu de données intégré - par nombre de cylindres, combien de voitures, et leur consommation et puissance moyennes :
Onze voitures à 4 cylindres avec une moyenne d'environ 26,7 mpg, sept à 6 cylindres autour de 19,7, quatorze à 8 cylindres autour de 15,1 - et la puissance qui marche dans l'autre sens. Deux appels, tout un tableau de synthèse : c'est le genre de question à laquelle l'agrégation par groupe existe pour répondre.
Ce que tu retiens
table()pour les effectifs,prop.table()pour les proportions.tapply(values, groups, fn)renvoie un vecteur nommé - coups d'œil rapides, consultations faciles.aggregate(value ~ group, data, FUN)renvoie un data frame ;+ajoute des variables de groupement,cbind()ajoute des colonnes de valeurs.- Le
group_by() |> summarize(n = n(), avg = mean(x), .groups = "drop")de dplyr est le standard moderne pour des résumés à plusieurs statistiques. - Choisis selon la forme de sortie ; ils s'accordent tous sur les nombres.
Prochaine étape : combiner des tableaux qui partagent une clé - merge() et la famille des jointures de dplyr.
Questions fréquentes
Comment calculer la moyenne par groupe en R ?
R de base a deux outils : tapply(df$value, df$group, mean) renvoie un vecteur nommé de moyennes par groupe, et aggregate(value ~ group, data = df, FUN = mean) renvoie le même résultat sous forme de data frame. En dplyr : df |> group_by(group) |> summarize(avg = mean(value)).
Comment compter les occurrences par groupe en R ?
table(df$group) compte les lignes par valeur de groupe en un seul appel ; table(df$a, df$b) croise deux colonnes. En dplyr, count(df, group) fait la même chose et renvoie un data frame, plus facile à retraiter.
Que fait aggregate() en R ?
aggregate() découpe un data frame selon une ou plusieurs colonnes de groupement, applique une fonction à chaque morceau, et renvoie un data frame de résultats. L'interface formule se lit naturellement : aggregate(sales ~ region + quarter, data = df, FUN = mean) signifie les ventes, groupées par région et trimestre, moyennées.
Quelle est la différence entre tapply et aggregate ?
Même calcul, forme de sortie différente. tapply() renvoie un vecteur nommé (ou un tableau pour deux variables de groupement) - pratique pour des consultations rapides. aggregate() renvoie un data frame - mieux quand le résultat alimente une analyse ultérieure, une jointure ou un graphique. Dans le doute, aggregate().