Eine wichtige Funktion zur Datenmanipulation ist die Funktion apply() (wie auch ihre Tochterfunktionen lapply(), sapply() und tapply()). Mit ihr können beliebige Funktionen auf die Reihen und/oder Spalten eines Datenframes (oder einer Matrix) angewendet werden. Dadurch erlaubt sie es in vielen Fällen, Loop-Schleifen und Redundanzen zu vermeiden.
Zur Verdeutlichung sei folgendes Beispiel gegeben:
Name Alter Groesse Gewicht
1 Hans 56 178 105
2 Gerda 59 172 67
3 Kurt 58 181 95
4 Maria 58 166 89
Angenommen, wir wollen die Mittelwerte der drei numerischen Variablen bestimmen, dann könnten wir so vorgehen:
mean(df$Alter)
[1] 57.75
mean(df$Groesse)
[1] 174.25
mean(df$Gewicht)
[1] 89
Die Funktion apply() erlaubt es, die Werte in nur einem Aufruf zu erzeugen, indem die Funktion mean() auf die Werte jeder Spalte angewendet wird.
apply(df[,-1], MARGIN=2, FUN=mean)
Alter Groesse Gewicht
57.75 174.25 89.00
Wir übergeben der Funktion zunächst das Datenframe df ohne die Spalte Name (df[,-1]). Mit dem Parameter MARGIN wird festgelegt, wie apply() auf das Datenframe schauen soll:
MARGIN=1 - Reihe für Reihe
MARGIN=2 - Spalte für Spalte
MARGIN=3 - beides zusammen
Über den Parameter FUN wird die zu verwendende Funktion (in diesem Falle mean()) ohne Klammern angegeben.
Möchten wir nun die Standardabweichung der drei Variablen berechnen, lautet der Aufruf entsprechend:
apply(df[,-1], MARGIN=2, FUN=sd)
Alter Groesse Gewicht
1.258306 6.652067 16.083117
Es ist wichtig, die nicht-numerische Variable Name vor dem apply()-Aufruf herauszufiltern. Denn wenn die zu verwendende Funktion bei nur einer Reihe fehl schlägt, liefert apply() nur eine Reihe NAs und Warnmeldungen zurück.
# aufruf mit Spalte "Name" schlägt fehlapply(df, MARGIN=2, FUN=mean)
Warning in mean.default(newX[, i], ...): Argument ist weder numerisch noch
boolesch: gebe NA zurück
Warning in mean.default(newX[, i], ...): Argument ist weder numerisch noch
boolesch: gebe NA zurück
Warning in mean.default(newX[, i], ...): Argument ist weder numerisch noch
boolesch: gebe NA zurück
Warning in mean.default(newX[, i], ...): Argument ist weder numerisch noch
boolesch: gebe NA zurück
Name Alter Groesse Gewicht
NA NA NA NA
Möchten wir die Werte der Probanden beispielsweise aufaddieren, lassen wir per apply() die Funktion sum() reihenweise über die Daten laufen. Hierzu setzen wir den Parameter MARGIN=1.
# laufe pro-Reihe über die Datenapply(df[,-1], MARGIN=1, FUN=sum)
[1] 339 298 334 313
Wir können jede Funktion per apply() auf die Variablen loslassen:
# Wurzel aus jedem Wert ziehenapply(df[,-1], MARGIN=2, sqrt)
Da wir wissen, dass der Parameter MARGIN an zweiter Stelle kommt, müssen wir ihn dort nicht immer ausschreiben, sondern können einfach 1, 2 oder 3 schreiben.
# Häufigkeitstabelle für jede Variable# MARGIN=2 muss nicht ausgeschrieben werdenapply(df[,-1], 2, FUN=jgsbook::freqTable)
Es ist möglich, die Parameter, welche an die auszuführende Funktion übergeben werden müssen, aus dem Datenframe selbst zu ziehen. Erzeugen wir zur Verdeutlichung folgendes Datenframe:
Name Geschwindigkeit Strecke
1 Jerome 120 200
2 Nadine 25 34
3 Dominik 32 50
4 Ella 80 100
Jetzt programmieren wir die Funktion zeit(), welche ausrechnet, wie lange die Personen für die Strecke mit der angegebenen Geschwindigkeit benötigt haben. Die Funktion nimmt die Werte velo (Geschwindigkeit) und dist (Strecke) entgegen.
# Funktion programmierenzeit <-function(velo, dist){# rechne Distanz / Geschwindigkeit# runde auf 2 Stellen zeit <-round(dist/velo, 2)return(zeit)}
Um die Funktion zeit() auf jede Reihe des Datenframes anzuwenden, wobei die Werte von Geschwindigkeit und Strecke jeweils als Parameter übergeben werden, müssen wir zunächst per MARGIN=1 angeben, dass apply() die Daten Reihe-für-Reihe verarbeiten soll.
Der Trick besteht darin, im Paramter FUN eine temporäre Funktion function(line) anzugeben. Diese ruft ihrerseits die Funktion zeit() (diesmal mit Klammern) auf, und übergibt die Parameter per line("SPALTENNAME").
# Übergebe die Werte an die Funktion zeit()apply(df[,-1], MARGIN=1, function(line) zeit(line["Geschwindigkeit"], line["Strecke"]))
[1] 1.67 1.36 1.56 1.25
Wenn die Parameter dist und velo mit ihrem Namen angegeben werden, ist die Reihenfolge der Parameter egal.
# Parameter dist und velo direkt angebenapply(df[,-1], MARGIN=1, FUN=function(line) zeit(dist=line["Strecke"], velo=line["Geschwindigkeit"]))
[1] 1.67 1.36 1.56 1.25
Als temporäre Hilfsfunktionen können verschiedene Arten verwendet werden:
function(x) - übergibt jeden Wert einzeln und nacheinander jeweils als Parameter an die Funktion, wobei x für spezifische Parameter referenziert werden kann (siehe Abschnitt 20.0.3 für ein Beispiel).
function(line) - übergibt die Werte der gesamte Datenreihe als Parameter an die Funktion, wobei die einzelnen Variablenwerte per line["SPALTENNAME"] referenziert werden können.
In einem weiteren Beispiel wollen wir Fallzahlen für spezifische Werte von e, P und dem Konfidenzlevel berechnen (siehe Abschnitt 33.12.2). Hierzu nutzen wir die Funktion samplingbook::sample.size.prop(), wobei die Erweiterung samplingbook::sample.size.prop()$n nur die Fallzahlen zurückgibt.
Sollen die Werte des Ausgangsvektors als spezifischer Parameter der auszuführenden Funktion übergeben werden, muss wieder auf eine temporäre Hilfsfunktion function(x) zurückgegriffen werden. Im folgenden Aufruf sollen die Werte des Vektors N jeweils als Paramenter N an die Funktion samplingbook::sample.size.mean() übergeben werden.
# Rufe für jeden Wert x im Vektor N die Funktion auf, # wobei Parameter N=x istsapply(N, FUN=function(x) samplingbook::sample.size.mean(e=0.05, S=0.3, level=0.90, N=x) )
Geschlecht Alter
1 m 45
2 w 34
3 m 46
4 m 41
5 w 31
6 w 29
7 d 24
8 d 25
9 d 26
Angenommen, wir möchten nun die Mittelwerte des Alters in Abhängigkeit zum Geschlecht bestimmen, so können wir tapply() verwenden.
tapply(df$Alter, df$Geschlecht, mean)
d m w
25.00000 44.00000 31.33333
Wie bei den Schwesterfunktionen lassen sich weitere Parameter per Komma übergeben.
# Berecne IQR so wie SPSS (type=6)tapply(df$Alter, df$Geschlecht, IQR, type=6)
d m w
2 5 5
große Schlarmann, J. (2024b). Statistik mit R und RStudio - EinNachschlagewerk für Gesundheitsberufe. Hochschule Niederrhein. https://www.produnis.de/R
große Schlarmann, J. (2024a). Statistik mit R und RStudio - EinNachschlagewerk für Gesundheitsberufe. Hochschule Niederrhein. https://www.produnis.de/R