Menu

Group By und Summarize in R (aggregate, tapply, dplyr)

Alle Wege, um in R Statistiken pro Gruppe zu berechnen: Zählen mit table(), tapply() für eine Statistik pro Gruppe, das Formel-Interface von aggregate() und dplyr's group_by() mit summarize().

Diese Seite enthält ausführbare Editoren - bearbeiten, ausführen und Ausgabe sofort sehen.

Zeilen pro Gruppe zählen: table()

Die einfachste Group-by-Frage ist "Wie viele von jedem?" - und Base R beantwortet sie in einem Aufruf. table() zählt, wie oft jeder Wert vorkommt:

Eine Spalte liefert Zählungen pro Wert; zwei Spalten liefern eine vollständige Kreuztabelle (Regionen als Zeilen, Pläne als Spalten). Für "welcher Anteil?" in prop.table(table(...)) einwickeln. table() ist der schnellste Weg zu einer Häufigkeitsantwort in ganz R - greif zu nichts Schwererem, wenn nur eine Zählung gebraucht wird.

Eine Statistik pro Gruppe: tapply()

tapply(werte, gruppen, funktion) teilt den ersten Vektor nach dem zweiten auf und wendet die Funktion auf jedes Stück an:

Das Ergebnis ist ein benannter Vektor - Gruppenlabels als Namen, Statistiken als Werte -, was ihn perfekt für schnelle Nachschlagevorgänge macht (means["EU"]). Der Name entschlüsselt sich als "table apply": eine Funktion entlang einer Gruppierungstabelle anwenden. Sie gehört zur selben Familie wie sapply() und lapply(), behandelt in der Doku zur apply-Familie.

Die Grenze von tapply() ist die Form: Ein benannter Vektor ist unhandlich zum Mergen, Plotten oder Weiterverarbeiten. Wenn die Zusammenfassung ein Zwischenschritt statt der finalen Antwort ist, will man einen Data Frame zurück - und genau den liefert das nächste Werkzeug.

Das Formel-Arbeitspferd: aggregate()

aggregate() ist das vollwertige Group-by von Base R: Es gibt einen Data Frame zurück, und sein Formel-Interface liest sich wie der Satz, den man sagen würde. wert ~ gruppe bedeutet "wert, aufgeschlüsselt nach gruppe":

Gruppierer hinzuzufügen ist einfach + weitere_spalte in der Formel - der zweite Aufruf summiert pro Kombination aus Region und Quartal. Man kann auch mehrere Wertspalten auf einmal aggregieren, mit cbind(a, b) ~ gruppe. Weil die Ausgabe ein gewöhnlicher Data Frame ist, passt sie direkt in einen Merge, eine Sortierung oder einen Plot - das ist das Base-Werkzeug, zu dem man für gruppierte Zusammenfassungen standardmäßig greift.

Ein stilles Verhalten sollte man kennen: Das Formel-Interface verwirft vor der Aggregation Zeilen mit NA in irgendeiner verwendeten Spalte. Meist genau das, was man will; gelegentlich die Erklärung für eine verdächtig niedrige Zählung.

Der dplyr-Weg: group_by() + summarize()

Der moderne Standard ist dplyr's Zwei-Verben-Muster - group_by() deklariert die Gruppierung, summarize() verdichtet jede Gruppe zu einer Zeile und berechnet so viele Statistiken, wie man benennt (statisch; die Sandbox führt nur Base R aus):

library(dplyr)

sales |>
    group_by(region) |>
    summarize(
        n     = n(),
        total = sum(amount),
        avg   = mean(amount)
    )

Hier übertrifft dplyr Base R wirklich: mehrere Statistiken pro Gruppe in einem lesbaren Aufruf - aggregate() braucht dafür Verrenkungen -, dazu n() gratis, und das Ergebnis fließt direkt in die nächste Pipe. (summarise() ist dieselbe Funktion, UK-Schreibweise.)

Eine Sache verwirrt Neulinge: Bei mehreren Gruppierern schält summarize() nur den letzten ab und lässt das Ergebnis weiterhin gruppiert - und gibt eine Meldung dazu aus. Sag explizit, was du willst, mit dem .groups-Argument: summarize(avg = mean(amount), .groups = "drop") gibt einen einfachen, ungruppierten Frame zurück - die richtige Standardgewohnheit. Ein gruppierter Frame, der sich in späteren Code schleicht, lässt mutate() und Co. stillschweigend pro Gruppe arbeiten - eine klassische Quelle verwirrender Ergebnisse.

Die Wahl zwischen ihnen

  • Eine Zählung - table(), nichts schlägt einen einzigen Aufruf.
  • Eine Statistik, schneller Blick - tapply(), und die Antwort vom benannten Vektor ablesen.
  • Data Frame als Ausgabe, reine Base-Umgebung - aggregate() mit einer Formel.
  • Mehrere Statistiken, Teil einer Pipeline oder irgendetwas Ambitioniertes - group_by() |> summarize().

Es gibt keine falsche Antwort unter ihnen - alle berechnen dieselben Zahlen -, aber das Werkzeug an die benötigte Ausgabeform anzupassen spart den Konvertierungsschritt danach. Mittelwerte, Mediane und Streuungsmaße selbst werden in der deskriptiven Statistik behandelt.

Durchgerechnetes Beispiel: mtcars nach Zylinderanzahl

Alles zusammen an einem eingebauten Datensatz - pro Zylinderanzahl: wie viele Autos, und ihr durchschnittlicher Verbrauch und ihre durchschnittliche Leistung:

Elf 4-Zylinder mit im Schnitt etwa 26,7 mpg, sieben 6-Zylinder um 19,7, vierzehn 8-Zylinder um 15,1 - und die PS-Zahlen marschieren in die Gegenrichtung. Zwei Aufrufe, eine ganze Zusammenfassungstabelle: Genau für diese Art Frage existiert gruppierte Aggregation.

Was du mitnimmst

  • table() für Zählungen, prop.table() für Anteile.
  • tapply(werte, gruppen, fn) gibt einen benannten Vektor zurück - schnelle Blicke, einfache Lookups.
  • aggregate(wert ~ gruppe, data, FUN) gibt einen Data Frame zurück; + fügt Gruppierer hinzu, cbind() fügt Wertspalten hinzu.
  • dplyr's group_by() |> summarize(n = n(), avg = mean(x), .groups = "drop") ist der moderne Standard für Zusammenfassungen mit mehreren Statistiken.
  • Nach Ausgabeform wählen; bei den Zahlen sind sich alle einig.

Als Nächstes: Tabellen kombinieren, die einen Schlüssel teilen - merge() und die dplyr-Join-Familie.

Häufig gestellte Fragen

Wie berechne ich den Mittelwert pro Gruppe in R?

Base R hat zwei Werkzeuge: tapply(df$value, df$group, mean) gibt einen benannten Vektor von Gruppenmittelwerten zurück, und aggregate(value ~ group, data = df, FUN = mean) liefert dasselbe Ergebnis als Data Frame. In dplyr: df |> group_by(group) |> summarize(avg = mean(value)).

Wie zähle ich Vorkommen pro Gruppe in R?

table(df$group) zählt Zeilen pro Gruppenwert in einem Aufruf; table(df$a, df$b) erstellt eine Kreuztabelle zweier Spalten. In dplyr macht count(df, group) dasselbe und gibt einen Data Frame zurück, der sich leichter weiterverarbeiten lässt.

Was macht aggregate() in R?

aggregate() teilt einen Data Frame nach einer oder mehreren Gruppierungsspalten auf, wendet eine Funktion auf jedes Stück an und gibt einen Data Frame mit den Ergebnissen zurück. Das Formel-Interface liest sich natürlich: aggregate(sales ~ region + quarter, data = df, FUN = mean) bedeutet: sales, gruppiert nach region und quarter, gemittelt.

Was ist der Unterschied zwischen tapply und aggregate?

Gleiche Berechnung, unterschiedliche Ausgabeform. tapply() gibt einen benannten Vektor zurück (bzw. ein Array bei zwei Gruppierern) - praktisch für schnelle Nachschlagevorgänge. aggregate() gibt einen Data Frame zurück - besser, wenn das Ergebnis in weitere Analysen, einen Merge oder einen Plot einfließt. Im Zweifel: aggregate().

Coddy programming languages illustration

Lerne mit Coddy zu programmieren

LOS GEHT'S