Jakob Richter

aggregate() – Teil 2

Teil 1 findet sich hier: aggregate() – der Anfang

Der erste Teil lieferte ein einfaches Beispiel zur Nutzung der aggregate()-Funktion. Widmen wir uns nun einem etwas komplexeren Fall.

Verschiedene Gruppen erzeugen

Zunächst simulieren wir uns wieder einmal ein Datensatz mit ein paar Versuchsperson und ihrem Gewicht vor der Studie (gewicht1) und ihrem Gewicht nach der Studie (gewicht2). Außerdem brauchen wir natürlich noch Gruppen, die wir untersuchen wollen. Weisen wir den Versuchspersonen also noch zufällig eine Haarfarbe und die Therapie (1 Wöchige Diät aus ausschließlich Salat oder Pizza) zu.

1
2
3
4
5
6
7
8
set.seed(110)
gewicht1 <- rnorm(100,mean=90,sd=15) #Gewichte der Versuchspersonen vor dem Essen
gewicht2 <- rnorm(100,mean=100,sd=20) #Gewichte nach dem Essen
gewichte <- cbind.data.frame(gewicht1,gewicht2) #Datensatz mit beiden Gewichten
gewichte <- cbind(gewichte,zunahme=gewichte$gewicht2 - gewichte$gewicht1)    #die Zunahme hinzufügen
haarfarben <- sample(c("blond","rot","brünett","schwarz"),size=100,rep=T)
essen <- sample(c("Salat","Pizza"),size=100,rep=T)
einteilung <- list(haarfarbe=haarfarben,essen=essen)

In den letzten Zeilen haben wir also einen Vektor erzeugt mit 100 Zuteilungen für die Haarfarbe und 100 Zuteilungen für das Essen, was die Versuchspersonen verabreicht bekommen.

Was wird aggregate() jetzt tun?

Ganz einfach: Für alle Werte des Eingabevektors, die die gleiche Kombination von haarfarbe und essen haben wird die Funktion FUN= aufgerufen. Wenn die Funktion z.B. mean ist, wird das arithmetische Mittel von jeweils gewicht1, gewicht2 und zunahme gebildet von den Personen, die die gleiche Haarfarbe und die gleiche Diät hatten.

9
10
11
12
13
14
15
16
17
18
19
20
#Für die Zeilen für die haarfarbe und essen die gleiche Kombination haben, wird für jede Spalte die Funktion aufgerufen. Hier arithm. Mittel. Runden auf 0,01.
vergleich <- aggregate(gewichte,by=einteilung,FUN=function(x) round(mean(x),2))
vergleich
#   haarfarbe essen gewicht1 gewicht2 zunahme
# 1     blond Pizza    86.61    98.21   11.61
# 2   brünett Pizza    95.05    94.27   -0.78
# 3       rot Pizza    84.49   103.61   19.12
# 4   schwarz Pizza    93.72    95.77    2.05
# 5     blond Salat    83.54    92.06    8.52
# 6   brünett Salat    85.52    97.78   12.27
# 7       rot Salat    95.02    90.31   -4.72
# 8   schwarz Salat    90.74   102.73   11.99

Sehr gut, schon haben wir unser Ergebnis. Offensichtlich führt Pizza bei brünetten Menschen nicht zur Gewichtszunahme. Ebenso ist Salat für rothaarige besonders gesund. Moment mal? Sollten wir da nicht noch ein wenig mehr ausrechnen?

Können wir nicht noch mehr ausrechnen?

Ja das können/sollten wir und es ist sehr einfach. Wir verbinden einfach mit c() mehrere Berechnungen und geben den einzelnen Werten am besten noch sinnvolle namen wie z.B. c(mittel=mean(x),max=max(x)).

25
26
27
28
29
30
31
32
33
34
aggregate(gewichte$zunahme,by=einteilung,FUN=function(x) round(c(mittel=mean(x), Q=quantile(x,probs=c(0.25,0.75)),N=length(x)),2))
#   haarfarbe essen x.mittel x.Q.25% x.Q.75%    x.N
# 1     blond Pizza    11.61   -5.63   27.61  16.00
# 2   brünett Pizza    -0.78   -9.30   11.69  13.00
# 3       rot Pizza    19.12    1.19   30.92  12.00
# 4   schwarz Pizza     2.05  -19.45   17.00  11.00
# 5     blond Salat     8.52  -13.37   15.30  12.00
# 6   brünett Salat    12.27   -1.05   31.06  13.00
# 7       rot Salat    -4.72  -25.10   11.00  12.00
# 8   schwarz Salat    11.99    1.17   19.44  11.00

Hier haben wir als Eingabedaten nur einen Vektor (gewichte$zunahme) genutzt, da ansonsten die Berechnungen für jede Spalte der Eingabedaten ausgeführt wird. Schon sehen wir, wie dumm unsere erste Schlussfolgerung war. Jetzt da wir auch die minimalen und maximalen Gewichtszunahmen in den Gruppen sehen fällt auf, dass die Untergruppen einerseits recht klein sind und die Streuung in ihnen viel Interpretationsspielraum lässt.

Ok, jetzt in einfach

Zur Abwechslung nutzen wir mal den Datensatz mtcars aus R.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
data(mtcars) #kann man weglassen
?mtcars
aggregate(qsec~gear+am,data=mtcars,function(x) {
  mittel <- mean(x)
  schnell <- min(x)
  schnellstesauto <- row.names(mtcars)[mtcars$qsec==schnell]
  vector <- c(mean=mittel, min=schnell, fastestcar=schnellstesauto)
  return(vector)
})
#   gear am qsec.mean qsec.min qsec.fastestcar
# 1    3  0    17.692    15.41      Camaro Z28
# 2    4  0    20.025     18.3        Merc 280
# 3    4  1    18.435    16.46       Mazda RX4
# 4    5  1     15.64     14.5  Ford Pantera L

Hier wurde die Formelschreibweise genutzt, durch data=mtcars weiß aggregate() dass es die Variablen innerhalb des Datensatzes finden kann. Man kann jedoch auch die Namen von Vektoren in die Formel schreiben (z.B. mtcars$qsec~mtcars$gear). Wie ist die Formel qsec~gear+am zu interpretieren ist sollte die Ausgabe erklären.
Am schnellsten sind also im Schnitt die Autos mit manueller Schaltung (am=0) und 5 Gängen (gear=5).

Leave a Reply