Überprüfung auf Vorhandensein, Zufälligkeit und Umgang
Letzte Änderung am 26. Februar 2021
Einleitung
Es kann in der Praxis häufiger vorkommen, dass Datensätze unvollständig sind z.B. wenn Teilnehmende einer Befragung nicht alle Fragen beantworten. Diese fehlenden Einträge nennt man Missings. In R werden sie (bei numeric) zumeist mit NA
(not available) gekennzeichnet.
NA
noch?
Beim Datentyp numeric (Zahlen) sind fehlende Werte durch NA
oder durch NaN
(Not a Number) gekennzeichnet.
num_vector <- c(1, 4, NA, NaN)
num_vector
[1] 1 4 NA NaN
is.na(num_vector)
[1] FALSE FALSE TRUE TRUE
Die Funktion is.na()
gibt für jedes Element ein TRUE
wenn es fehlt bzw. ein FALSE
wenn es vorhanden ist. Wir werden im Laufe des Kapitels verschiedene Kombinationsmöglichkeiten für diese Funktion kennen lernen.
NaN
entstehen z.B. bei unlösbaren Rechnungen wie Division durch \(0\).
num_vector[1] <- num_vector[4]/0
num_vector
[1] NaN 4 NA NaN
is.na(num_vector)
[1] TRUE FALSE TRUE TRUE
Beim Datentyp character (Buchstaben, Zeichen) hingegen könnten fehlende Eingaben auch durch ""
(leere Felder) gekennzeichnet sein z.B. wenn bei Freitextfeldern in einer Umfrage nichts eingegeben wurde. Das wird in R aber nicht automatisch als fehlender Wert erkannt.
NA
eine selbstständige Kodierung ist, und nicht als character kodiert wird.
Später lernen wir, wie wir Werte auf NA
umkodieren können.
Wir beschränken uns in vorliegendem Kapitel auf NA
in numerischen Datentypen (d.h. quantitative Daten).
Fehlende Werte sind grundsätzlich mit drei Schwierigkeiten verbunden:
Daher ist es sehr wichtig, sich vor der Auswertung einen Überblick über die fehlenden Werte zu verschaffen.
In diesem Kapitel schauen wir uns an, ob und wenn ja, wo und wie viele Missings sich im Datensatz befinden. Außerdem gibt es einen groben Überblick darüber, ob Missings zufällig sind und wie man mit ihnen umgehen kann.
Der Umgang mit Missings ist ein komplexes Thema. In diesem Kapitel werden wir uns auf zwei gängige Methoden zum Umgang mit Missings beschränken. In Abhängigkeit der eigenen Fragestellung empfiehlt es sich, passende Methoden zu recherchieren.
Das ist der Code für den Datensatz, an dem wir in diesem Kapitel arbeiten werden. Wenn du die Funktionen, die in diesem Kapitel vorgestellt werden, ausprobieren möchtest, führe den Code aus und erstelle den Datensatz.
# Data Frame erstellen
daten <- matrix(c(-99, 0, 1, 3, 2,
1, 2, 3, 2, 0,
NA, 1, 3, 99, 0,
1, 3, 3, 1, 2,
2, 0, 2, 99, 3), nrow = 5, ncol = 5)
# in Dataframe umwandeln
daten <- data.frame(daten)
# Spalten und Zeilen benennen
colnames(daten) <- c("Var_1", "Var_2", "Var_3", "Var_4", "Var_5")
rownames(daten) <- c("Vpn_1", "Vpn_2", "Vpn_3", "Vpn_4", "Vpn_5")
Var_1 Var_2 Var_3 Var_4 Var_5
Vpn_1 -99 1 NA 1 2
Vpn_2 0 2 1 3 0
Vpn_3 1 3 3 3 2
Vpn_4 3 2 99 1 99
Vpn_5 2 0 0 2 3
Wenn du Variablen, die Missings enthalten, für eine Analyse nutzt, denke immer daran, dass sich damit auch die Stichprobengröße \(N\) für diese spezifische Auswertung ändert.
In manchen Anwendungen werden Missings nicht mit NA
sondern anderweitig kodiert (z.B. bei Unipark mit 99
oder -99
). Daher müssen wir dafür sorgen, dass R Missings auch als solche erkennt. Das gewährleistet man, indem man alle Missings auf NA
setzt.
Wenn man weiß, wie Missings im Datensatz kodiert sind, kann man gleich zu Wie kann ich die Missings auf NA
setzen? springen. Wenn man weiß, dass alle Missings einheitlich mit NA
kodiert sind, kann man den ganzen Abschnitt auslassen.
Um herauszufinden, ob auch alle Missings einer Variablen korrekterweise mit NA
kodiert sind, vergleichen wir die angegebenen Werte der Variablen in unseren Daten mit den möglichen Ausprägungen der Variablen (die wir zumeist im Codebuch finden; in unserem Fall steht diese Information in der Einleitung).
Dazu kombinieren wir die Funktion unique()
, die uns alle Werte eines Vektors (einmalig) ausgibt, mit der Funktion sort()
, die uns die Werte noch sortiert (standarmäßig aufsteigend). Mit na.last = TRUE
gibt uns sort()
sogar die Information zum Vorhandensein von Missings am Ende aus.
Da wir wissen, dass Var_3
nur die Ausprägungen \(0,1,2,3\) annehmen kann, können wir schließen, dass \(99\) auch ein Missing sein muss.
Wenn man also alle möglichen Ausprägungen der Variablen kennt, kann man auf diese Weise einfach herausfinden, ob noch anderweitig kodierte Missings im Datensatz vorliegen.
Wenn der Datensatz sehr groß ist, ist der oben gezeigte Ansatz allerdings sehr mühsam. Dann können wir die Funktion sapply()
integrieren, um unique()
und sort()
auf jede Variable im Datensatz anzuwenden. Diese hat die Form sapply(Daten, Funktion).
Da wir zwei Funktionen auf den Datensatz anwenden wollen - unique()
und sort()
- müssen wir sapply()
zweimal anwenden:
$Var_1
[1] -99 0 1 2 3
$Var_2
[1] 0 1 2 3
$Var_3
[1] 0 1 3 99 NA
$Var_4
[1] 1 2 3
$Var_5
[1] 0 2 3 99
In Var_1
gibt es die Ausprägung -99
und in Var_5
die Ausprägung 99
, welche keine möglichen Ausprägungen sind. Es ist davon auszugehen, dass das ebenso Kodierungen für fehlende Werte sind.
NA
setzen?Nun wollen wir diese Missings umkodieren. Vorher wollen wir uns noch einmal anschauen, was passiert, wenn man das nicht macht.
Wenn man Missings im Datensatz nicht einheitlich auf NA
kodiert, nimmt R an, dass es sich um gültige Werte handelt. Das führt dann zu falschen Ergebnissen. Das schauen wir uns exemplarisch einmal am Mittelwert der Spalte Var_3
an.
Var_1 Var_2 Var_3 Var_4 Var_5
Vpn_1 -99 1 NA 1 2
Vpn_2 0 2 1 3 0
Vpn_3 1 3 3 3 2
Vpn_4 3 2 99 1 99
Vpn_5 2 0 0 2 3
# Mittelwert vor Umkodierung
mean(daten$Var_3, na.rm=TRUE)
[1] 25.75
Nun kodieren wir die Missings in Var_3
einheitlich um …
# Umkodierung für einzelne Variablen
daten$Var_3[daten$Var_3 == 99] <- NA
Der Befehl ersetzt in daten Elemente der Spalte Var_3, welche die Ausprägung 99
besitzen, mit NA
.
Var_1 Var_2 Var_3 Var_4 Var_5
Vpn_1 -99 1 NA 1 2
Vpn_2 0 2 1 3 0
Vpn_3 1 3 3 3 2
Vpn_4 3 2 NA 1 99
Vpn_5 2 0 0 2 3
… und schauen uns den Mittelwert von Var_3
wieder an.
# Mittelwert nach Umkodierung
mean(daten$Var_3, na.rm=T)
[1] 1.333333
Hätten wir die Missings nicht einheitlich auf NA kodiert, hätten wir errechnet, dass der Mittelwert von Var_3
25.75 anstatt ~1.33 betragen würde.
Wir sehen also, dass es sehr wichtig ist, in Erfahrung zu bringen, ob im Datensatz alle Missings einheitlich auf NA gesetzt sind, und wenn nicht, diese einheitlich zu kodieren, da man sonst falsche Ergebnisse erhält.
Jetzt enthält die Spalte Var_3
schon keine Elemente mit der Ausprägung 99
mehr, aber in Var_1
gibt es noch ein -99
und in Var_5
noch ein 99
.
Um nicht einzeln Spalten und Ausprägungen ansprechen zu müssen, kann man alles in einem Befehl kombinieren.
# Umkodierung für den gesamten Datensatz
daten[daten == 99 | daten == -99] <- NA
Hiermit werden im gesamten daten
jene Elemente, welche die Ausprägung 99
oder -99
besitzen, durch NA
ersetzt.
Wenn wir wissen wie unsere fehlenden Werte kodiert sind, wollen wir in einem nächsten Schritt natürlich wissen, ob ein Datensatz überhaupt Missings enthält. Es gibt zahlreiche Ansätze, um das herauszufinden. Einige davon schauen wir uns einmal genauer an.
Bei kleineren Datensätzen ist eine visuelle Inspektion möglich. Dafür nutzt man entweder View()
(Großbuchstabe am Anfang beachten!) oder man klickt auf den Datensatz im Environment (oberes rechtes Panel).
Var_1 Var_2 Var_3 Var_4 Var_5
Vpn_1 NA 1 NA 1 2
Vpn_2 0 2 1 3 0
Vpn_3 1 3 3 3 2
Vpn_4 3 2 NA 1 NA
Vpn_5 2 0 0 2 3
Um zu überprüfen, ob ein Datensatz mindestens einen fehlenden Wert enthält, kann man anyNA()
nutzen. Man bekommt ein TRUE
(d.h. ja, mindestens ein Missing enthalten) oder FALSE
(d.h. nein, keine Missings enthalten) ausgegeben.
anyNA(daten)
[1] TRUE
Um einen groben Eindruck davon zu bekommen, welche Elemente fehlen, kann man is.na()
nutzen. Der Output besteht aus FALSE
oder TRUE
für jedes Element des Datensatzes. TRUE
bedeutet dabei, dass an dieser Stelle ein Missing ist.
is.na(daten)
Var_1 Var_2 Var_3 Var_4 Var_5
Vpn_1 TRUE FALSE TRUE FALSE FALSE
Vpn_2 FALSE FALSE FALSE FALSE FALSE
Vpn_3 FALSE FALSE FALSE FALSE FALSE
Vpn_4 FALSE FALSE TRUE FALSE TRUE
Vpn_5 FALSE FALSE FALSE FALSE FALSE
Bei is.na()
und anyNA()
wird auch NaN
(Not a number; entsteht bei unlösbaren Rechnungen) mitgezählt. Da Zweitere aber wesentlich seltener vorkommen, konzentrieren wir uns nur auf NA
.
Den logischen Vektor, den is.na()
erzeugt, kann man mit which()
kombinieren, um sich die Positionen der Missings ausgeben zu lassen. Mithilfe des Arguments arr.ind = TRUE
lässt man sich die Reihe und die Spalte dieser ausgeben.
Ohne arr.ind = TRUE
würde man nur die Indizes ausgegeben bekommen. Für Matrizen sind diese weniger leicht zu nutzen, weil die Nummerierung fortlaufend spaltenweise vorliegt. In unserem Fall einer 5 x 5 Matrix heißt das z.B., dass das Element in der 1. Zeile der 3. Spalte (also der eine fehlende Wert) den Index 11 trägt.
Bei Vektoren kann man arr.ind = TRUE
weglassen, da diese entweder nur aus einer Spalte oder einer Zeile bestehen.
Die genaue Anzahl der Missings zu kennen ist wichtig, um ein Gefühl dafür zu kriegen, wie vollständig ein Datensatz ist. Dazu kombinieren wir die is.na()
-Funktion mit anderen Funktionen, die FALSE
(d.h. vorhandenen Werte) und TRUE
(d.h. fehlenden Werte) zählen.
Zuerst schauen wir uns die Gesamtanzahl der Missings aller Elemente im Datensatz an.
Spaltenweises Zählen der Missings gibt Informationen über mögliche Probleme mit bestimmten Variablen. Zeilenweises Zählen der Missings gibt beispielsweise Informationen über Teilnehmende, die die Fragen nicht vollständig beantwortet haben.
Es ist daher wichtig, sich einen Überblick darüber zu machen, ob sich bei bestimmten Variablen oder bei bestimmten Personen besonders viele Missings häufen. Wenn das der Fall sein sollte, muss man überlegen, wie man damit umgeht (dazu mehr im späteren Verlauf).
Wenn wir eine bestimmte Spalte oder Zeile betrachten möchten, können wir die is.na()
-Funktion mit der table()
-Funktion kombinieren. Zweiteres sorgt dafür, dass wir eine Häufigkeitstabelle von TRUE
und FALSE
ausgegeben bekommen.
Wir können auf verschiedenem Wege auf eine Spalte bzw. Zeile eines Datensatzes referenzieren.
FALSE TRUE
4 1
FALSE TRUE
4 1
FALSE TRUE
3 2
FALSE TRUE
4 1
FALSE TRUE
3 2
Die ersten drei vorgestellten Möglichkeiten, $
und Datensatz[“Spalten- bzw. Zeilenname”], funktionieren nur bei Dataframes, und nicht bei Matrizen. Die Möglichkeit der Indexierung können wir auch bei Matrizen nutzen.
Wenn man sich einen Überblick über die Missings in allen Variablen bzw. bei allen Personen verschaffen möchte, kann man dafür colSums()
bzw. rowSums()
mit dem is.na()
-Befehl kombinieren. Damit werden spalten- bzw. zeilenweise Summen von TRUE
(d.h. den Missings) gebildet.
Um die Größenordnung der Missings besser beurteilen zu können, sollte man sich der maximal möglichen Anzahl der Elemente in einer Spalte bzw. Zeile bewusst sein. Diese können wir mit nrow()
bzw. ncol()
in Erfahrung bringen.
Var_1 Var_2 Var_3 Var_4 Var_5
1 0 2 0 1
# ... im Vergleich zur maximalen Anzahl an Beantwortungen
nrow(daten)
[1] 5
Vpn_1 Vpn_2 Vpn_3 Vpn_4 Vpn_5
2 0 0 2 0
# ... im Vergleich zur maximalen Anzahl der beantwortbaren Fragen
ncol(daten)
[1] 5
Mit der Funktion aggr()
aus dem Paket VIM kann man sich zwei Plots ausgeben lassen, die den relativen Anteil von Missings in den einzelnen Variablen und die Anzahl an Missings in bestimmten Kombinationen von Variablen (d.h. in den Zeilen) ausgeben.
Wenn man summary(aggr())
nutzt, bekommt man sowohl die grafische Visualisierung als auch eine Übersicht der Häufigkeiten.
Missings per variable:
Variable Count
Var_1 1
Var_2 0
Var_3 2
Var_4 0
Var_5 1
Missings in combinations of variables:
Combinations Count Percent
0:0:0:0:0 3 60
0:0:1:0:1 1 20
1:0:1:0:0 1 20
Im linken Plot sehen wir, dass nur Missings in Var_1, Var_3 und Var_5 vorhanden sind. Außerdem sehen wir auf der \(y\)-Achse den relativen Anteil an Fällen in den Variablen. In der Übersicht unter der Tabelle sehen wir die absoluten Häufigkeiten für alle Variablen (Missings per variable
). Im rechten Plot sehen wir die vorhanden Kombinationen von Missings in den Variablen. Blau zeigt an, dass kein Missing vorhanden ist; rot zeigt an, dass ein Missing vorhanden ist. Beispielsweise zeigt die unterste Reihe (die komplett blau ist) eine Kombination, in der keine Missings in Variablen vorhanden sind. Rechts daneben sieht man einen Balken, der den Anteil dieser Kombination im Verhältnis zu den anderen Kombinationen darstellt. Der Balken in der untersten Reihe ist der größte, d.h. dass diese Kombination am häufigsten vorkommt und somit die meisten Fälle (Zeilen) im Datensatz keine Missings enthalten. Leider bekommen wir hier keine Häufigkeiten dafür angezeigt. Dazu können wir aber in die unten stehende Übersicht schauen. (Missings in combinations of variables
), in der wir absolute und relative Häufigkeiten ausgegeben bekommen.
Am Anfang des Kapitels wurde bereits erwähnt, dass systematische Missings eine Auswertung verzerren können. Was es aber genau bedeutet, wenn Missings zufällig oder nicht zufällig sind und wie man das überprüfen kann, beleuchten wir in diesem Abschnitt.
Es gibt grundlegend drei Mechanismen, die zur Entstehung von fehlenden Werten führen können: Missing Completely at Random (MCAR), Missing at Random (MAR) und Missing not at Random (MNAR). Im folgenden schauen wir uns die Definition dieser Arten an.
Fehlende Werte sind unabhängig von … | MCAR | MAR | MNAR |
---|---|---|---|
… allen andere Variablen | X | ||
… ihren eigentlichen (fehlenden) Ausprägungen | X | X |
MCAR ist eine strengere Annahme als MAR. Wenn die Daten MCAR sind, dann sind sie auch MAR. Bei MAR und MNAR kann es zu Parameterverzerrungen kommen, wenn man Methoden nutzt, welche die strengere Annahme MCAR voraussetzen.
Bsp.1: Das Löschen von Fällen wenn die Daten nicht MCAR sind.
Bsp.2: Die Nutzung der Maximum Likelihood Schätzung oder der multiplen Imputation wenn die Daten nicht (mindestens) MAR sind.
Schematisch könnte unser Vorgehen bei der Exploration der Zufälligkeit von Missings folgendermaßen aussehen:
Exemplarisch wollen wir uns einen möglichen Test anschauen, der überprüft, ob die Annahme von MCAR verletzt ist.
\(\chi^2\)-Test für multivariate Daten von Little (1988):
Dieser überprüft, ob es signifikante Unterschiede zwischen den Mittelwerten der Muster von fehlenden Werten gibt. Die Nullhypothese (\(H_0\)) besagt, dass die Mittelwerte der Variablen (Spalten) nicht in Abhängigkeit der Missingmuster variieren (MCAR). Die Alternativhypothese (\(H_1\)) besagt, dass die Mittelwerte sich zwischen den verschiedenen Mustern von Missings unterscheiden (MAR oder MNAR).
Auch hier muss man sich vorher überlegen, wo man das Signifikanzniveau \(\alpha\) setzt. Für unser Beispiel legen wir es entsprechend der gängigen Konventionen auf \(\alpha= 0.05\) fest.
Zur Durchführung des Tests in R greifen wir auf die Funktion mcar_test()
aus dem Paket naniar zu. Das laden wir uns über Github herunter (wofür wir wiederum das Paket remotes benötigen).
mcar_test()
kann wir nur mit (quantitativen) Daten des Typs numeric (integer und double), logical und factor umgehen.
# install.packages("remotes")
# remotes::install_github("njtierney/naniar")
library(naniar)
mcar_test(daten)
# A tibble: 1 x 4
statistic df p.value missing.patterns
<dbl> <dbl> <dbl> <int>
1 5.88 6 0.437 3
Als Output bekommen wir den \(\chi^2\)-Wert (statistic
), die Anzahl der Freiheitsgrade (df
), den p-Wert (p-value
), sowie die Anzahl der Missing-Muster (missing.patterns
).
Der \(p\)-Wert für den MCAR-Test für unseren Datensatz ist größer als die Irrtumswahrscheinlichkeit \(\alpha\). Dies bedeutet, dass wir die \(H_0\) beibehalten können und (bis auf weiteres) davon ausgehen, dass die MCAR-Annahme erfüllt ist.
Für mehr Informationen zu diesem Test siehe Little (1988).
Im Paket naniar gibt es noch viele weitere Funktionen zur Zusammenfassung, Visualisierung und Manipulation von fehlenden Werten. Auf der Github-Seite finden wir eine Übersicht einiger dieser Funktionen.
Es gibt verschiedene Möglichkeiten, um mit unvollständigen Datensätzen umzugehen. Diese sind mehr oder weniger geeignet in Abhängigkeit davon, welche Annahme (MCAR, MAR, MNAR) die Missings erfüllen. Es gibt aber keine einheitlichen Richtlinien darüber, wie man mit Missings umgehen sollte. Das liegt u.a. auch daran, dass schon die Überprüfung der Zufälligkeit von Missings schwierig ist. Wichtig ist grundsätzlich, dass man sich mit den Missings eines Datensatzes auseinander setzt und einen Weg findet, mit ihnen umzugehen, ohne dass dies die Ergebnisse verzerren könnte. Man muss also für die eigene Fragestellung und Auswertungsmethode einen geeigneten Weg finden.
Im Folgenden wollen wir uns darauf beschränken, uns einige gängige Methoden anzuschauen, die man nutzen kann, wenn die fehlenden Werte MCAR sind. Wenn diese Annahme nicht erfüllt ist, können bei Nutzung der folgenden Methoden verzerrte Parameterschätzungen resultieren.
Zwei grundlegende Möglichkeiten sind entweder ganze Fälle mit Missings zu exkludieren (listwise/casewise deletion) oder vorhandene Elemente von Fällen für einen Teil der Analysen zu nutzen (pairwise deletion). In vielen Funktionen in R können wir zwischen beiden Möglichkeiten entscheiden.
Nachteil von beiden (d.h. kompletter bzw. partieller Ausschluss von Zeilen) ist generell, dass die Stichprobengröße \(N\) sinkt und damit einhergehend größere Standardfehler und eine geringere Power resultieren. Ein weiteres Problem bei pairwise deletion ist außerdem, dass sich die Stichprobengröße \(N\) sowie die Zusammensetzung der Stichproben für unterschiedliche Analysen unterscheiden wird.
Eine weitere Möglichkeit mit fehlenden Werten umzugehen ist diese zu imputieren (d.h. diese “vorherzusagen”). Da Imputation aber ein vielschichtiges Thema mit vielen verschiedenen Methodiken ist, gehen wir im Weiteren nicht darauf ein.
Mit na.omit()
löscht man listwise/casewise, d.h. Fälle, die mindestens ein Missing aufweisen werden komplett gelöscht. Es ist ratsam, den damit neu erstellten Datensatz als ein neues Objekt zu speichern (anstatt den originalen Satensatz zu überschreiben):
daten_cw <- na.omit(daten)
Var_1 Var_2 Var_3 Var_4 Var_5
Vpn_2 0 2 1 3 0
Vpn_3 1 3 3 3 2
Vpn_5 2 0 0 2 3
Wir haben jetzt leider den Nachteil, dass unser Datensatz von fünf auf drei Personen geschrumpft ist (weil zwei Personen mindestens auf einer Variablen ein Missing hatten).
Abhängig von der eigenen Auswertung möchte man das vielleicht eher nicht so machen, sondern die vorhandenen Werte in den hier gelöschten Zeilen noch anderweitig nutzen.
Anstatt die Daten in einem ersten Schritt hinsichtlich der fehlenden Werte zu bereinigen, erlauben viele Funktionen den Umgang mit fehlenden Werten direkt mittels zusätzlicher Argumente zu spezifizieren. Um zu erfahren, welche Argumente eine Funktion nutzen kann, können wir im unteren rechten Panel bei Help nachschauen.
Dazu schauen wir uns exemplarisch drei verschiedene Funktionen und einige ihrer Möglichkeiten im Umgang mit fehlenden Werten an.
Mit lm()
können wir eine (einfache oder multiple) lineare Regression durchführen. Mit dem Parameter na.action
können wir über den Umgang mit den Missings bestimmen. Ein mögliches Argument dafür ist na.omit. Dabei wird bei Vorhandenseins eines Missings in einer Zeile die komplette Zeile aus der Berechnung genommen (listwise/casewise deletion). Das ist der Default dieser Funktion.
In manchen Situationen ist es wichtig, Informationen darüber zu haben, wo Missings in einer Zeile sind (z.B. bei der Prüfung der Annahmen der Unabhängigkeit der Fehlerterme in der Multiplen Linearen Regression). Wenn ich beispielsweise einen Boxplot der Residuen einer linearen Regression in einer bestimmten Gruppe erstellen möchte, benötige ich einen Vektor der Residuen, in dem noch die Information darüber enthalten ist, in welcher Zeile Werte fehlen. Wenn der Residuenvektor und der Gruppenvektor unterschiedliche Zeilenanzahlen - in Abhängigkeit der Missings - haben, kann ich den Boxplot sonst nicht erstellen. Dafür nutzen wir das Argument na.exclude. Hierbei werden die Indizes der Missings nicht einfach gelöscht (und dadurch die Zeilenanzahl reduziert) sondern gespeichert. Ansonsten ist die Berechnung äquivalent zu na.omit
(d.h. auch listwise/casewise deletion). Mittels residuals(lm_Ergebnisobjekt) können wir dann den Residuenvektor extrahieren.
Die Funktion mean()
enthält den Parameter na.rm
, welcher festlegt, ob einzelne fehlende Elemente vor der Ausführung der Funktion entfernt werden sollen. Mit TRUE entfernen wir die Missings; mit FALSE behalten wir sie. Bei vielen Funktionen ist letzteres voreingestellt, was häufig aber eine Durchführung der Funktion verhindert.
mean(daten$Var_1) # kann nicht berechnet werden weil Default na.rm = FALSE
[1] NA
mean(daten$Var_1, na.rm = TRUE)
[1] 1.5
Die Funktion colMeans()
, mit der wir Spaltenmittelwerte von mehrdimensionalen Datenstrukturen (z.B. Matrizen oder Dataframes) berechnen können, besitzt ebenfalls den Parameter na.rm
. TRUE lässt uns hier (direkt) pairwise deletion anwenden. Schauen wir uns das einmal genauer an.
Exemplarisch begrenzen wir uns auf die ersten drei Spalten von daten
mittels [, 1:3]
.
mean(daten[, 1], na.rm = TRUE)
mean(daten[, 2]) # na.rm=TRUE nicht notwendig
mean(daten[, 3], na.rm = TRUE)
[1] 1.5
[1] 1.6
[1] 1.333333
colMeans(daten[, 1:3], na.rm = TRUE)
Var_1 Var_2 Var_3
1.500000 1.600000 1.333333
Wie wir sehen, bekommen wir die gleichen Ergebnisse bei mean()
und colMeans()
. Beide nutzen (quasi) pairwise deletion. Allerdings sprechen wir nur im Fall von colMeans()
davon, weil es bei mean()
keine andere Möglichkeit gibt, als jeweils die fehlende Werte eines Vektors (eindimensionale Datenstruktur) zu entfernen oder eben nicht.
colMeans(daten_cw[, 1:3])
# daten_cw sind die mit na.omit() bereinigten Daten (listwise deletion)
Var_1 Var_2 Var_3
1.000000 1.666667 1.333333
Vergleichen wir diese Ergebnisse nun mit denen von oben, sehen wir, dass nur der Mittelwert von Var_3 gleich. Bei den Mittelwerten der beiden anderen Spalten unterscheiden sich die Ergebnisse.
Var_1 Var_2 Var_3
Vpn_1 NA 1 NA
Vpn_2 0 2 1
Vpn_3 1 3 3
Vpn_4 3 2 NA
Vpn_5 2 0 0
Die unterschiedlichen Spaltenmittelwerte kommen daher zustande, dass na.omit()
für alle Berechnungen Vpn_1 und Vpn_4 ausschließt (listwise/casewise deletion), wohingegen na.rm
die Missings nur in den Spalten ausschließt, die gerade zur Berechnung benötigt werden (pairwise deletion), z.B. Vpn_4 bei der Berechnung des Mittelwerts von Var_3, aber nicht bei denen von Var_1 und Var_2.
Mit cor()
können wir Korrelationstabellen berechnen. Dabei können wir mit dem Parameter use
festlegen, wie mit Missings umgegangen werden sollen. Wir beschränken uns hier auf zwei Möglichkeiten von use
. Mit complete.obs nutzen wir listwise/casewise deletion; mit pairwise.complete.obs nutzen wir pairwise deletion.
Um den Unterschied zwischen beiden Möglichkeiten besser zu verstehen, schauen wir uns die jeweiligen Korrelationstabellen (der ersten drei Variablen) an.
Da die Korrelationsmatrizen symmetrisch sind (d.h. ober- und unterhalb der Diagonalen gleich sind) wird jeweils die obere Diagonale für die Tabellen ausgeblendet.
Var_1 | Var_2 | Var_3 | |
---|---|---|---|
Var_1 | 1 | ||
Var_2 | -0.655 | 1 | |
Var_3 | -0.327 | 0.929 | 1 |
Var_1 | Var_2 | Var_3 | |
---|---|---|---|
Var_1 | 1 | ||
Var_2 | -0.308 | 1 | |
Var_3 | -0.327 | 0.929 | 1 |
Wenn man die beiden Korrelationstabellen vergleicht, sieht man, dass sich die Korrelation zwischen Var_1 und Var_2 unterscheidet. Das liegt daran, dass Vpn_4 in allen Berechnungen mit complete.obs
ausgeschlossen wurde, weil Var_3 dort ein Missing enthält, während pairwise.complete.obs
diese Zeile bei der Korrelation von Var_1 und Var_2 miteinbezogen hat.
Var_1 Var_2 Var_3
Vpn_1 NA 1 NA
Vpn_2 0 2 1
Vpn_3 1 3 3
Vpn_4 3 2 NA
Vpn_5 2 0 0
Im Gegensatz zu complete.obs
basieren die verschiedenen Korrelationen bei pairwise.complete.obs
auf Werten aus unterschiedlichen Zeilen (d.h. von unterschiedlichen Personen).
Für ein tiefergehenden Einblick empfehlen wir Euch die folgenden Arbeiten:
Allison, P. D. (2002). Missing Data. In P. D. Allison (Ed.), The Sage Handbook of Quantitative Methods in Psychology (pp.72-89). Thousand Oaks, CA: Sage Publications Ltd. Abgerufen über http://www.statisticalhorizons.com/wp-content/uploads/2012/01/Milsap-Allison.pdf
Cohen, J., Cohen, P., West, S. G., & Aiken, L. S. (2003). Missing Data. In J. Cohen, P. Cohen, S. G. West, & L. S. Aiken (Eds.), Applied Multiple Regression/Correlation Analysis for the Behavioral Sciences (S. 431-451). Hillsdale, NJ: Erlbaum.
(für HU-Studierende über ub.hu-berlin.de zugänglich)
Little, R. J. A. (1988). A test of missing completely at random for multivariate data with missing values. Journal of the American Statistical Association, 83(404), 1198–1202.
(für HU-Studierende über ub.hu-berlin.de zugänglich)
Schafer, J. L., & Graham, J. W. (2002). Missing Data: Our View of the State of the Art. Psychological Methods, 7(2), 147-177. Abgerufen über http://www.nyu.edu/classes/shrout/G89-2247/Schafer&Graham2002.pdf
Um eine möglichst exakte Replikation der Funktionen zu gewährleisten gibt es im folgenden relevante Angaben zum System (R-Version, Betriebssystem, geladene Pakete mit Angaben zur Version), mit welchem diese Seite erstellt wurde.
R version 4.0.3 (2020-10-10)
Platform: x86_64-pc-linux-gnu (64-bit)
Running under: Ubuntu 20.04.2 LTS
Matrix products: default
BLAS: /usr/lib/x86_64-linux-gnu/blas/libblas.so.3.9.0
LAPACK: /usr/lib/x86_64-linux-gnu/lapack/liblapack.so.3.9.0
locale:
[1] LC_CTYPE=de_DE.UTF-8 LC_NUMERIC=C
[3] LC_TIME=de_DE.UTF-8 LC_COLLATE=de_DE.UTF-8
[5] LC_MONETARY=de_DE.UTF-8 LC_MESSAGES=de_DE.UTF-8
[7] LC_PAPER=de_DE.UTF-8 LC_NAME=C
[9] LC_ADDRESS=C LC_TELEPHONE=C
[11] LC_MEASUREMENT=de_DE.UTF-8 LC_IDENTIFICATION=C
attached base packages:
[1] grid stats graphics grDevices utils datasets
[7] methods base
other attached packages:
[1] naniar_0.6.0.9000 kableExtra_1.3.4 knitr_1.31
[4] VIM_6.1.0 colorspace_2.0-0
loaded via a namespace (and not attached):
[1] httr_1.4.2 tidyr_1.1.2 sass_0.3.1
[4] jsonlite_1.7.2 viridisLite_0.3.0 carData_3.0-4
[7] bslib_0.2.4 assertthat_0.2.1 sp_1.4-5
[10] highr_0.8 cellranger_1.1.0 norm_1.0-9.5
[13] yaml_2.2.1 robustbase_0.93-7 pillar_1.5.0
[16] lattice_0.20-41 visdat_0.5.3 glue_1.4.2
[19] digest_0.6.27 rvest_0.3.6 htmltools_0.5.1.1
[22] Matrix_1.2-18 pkgconfig_2.0.3 haven_2.3.1
[25] purrr_0.3.4 scales_1.1.1 webshot_0.5.2
[28] ranger_0.12.1 svglite_2.0.0 openxlsx_4.2.3
[31] distill_1.2 rio_0.5.16 downlit_0.2.1
[34] tibble_3.0.6 generics_0.1.0 car_3.0-10
[37] ggplot2_3.3.3 ellipsis_0.3.1 nnet_7.3-14
[40] cli_2.3.0 magrittr_2.0.1 crayon_1.4.1
[43] readxl_1.3.1 evaluate_0.14 laeken_0.5.1
[46] fansi_0.4.2 MASS_7.3-53 forcats_0.5.1
[49] xml2_1.3.2 foreign_0.8-79 class_7.3-17
[52] tools_4.0.3 data.table_1.14.0 hms_1.0.0
[55] lifecycle_1.0.0 stringr_1.4.0 munsell_0.5.0
[58] zip_2.1.1 compiler_4.0.3 jquerylib_0.1.3
[61] e1071_1.7-4 vcd_1.4-8 systemfonts_1.0.1
[64] rlang_0.4.10 rstudioapi_0.13 rmarkdown_2.7
[67] boot_1.3-25 gtable_0.3.0 abind_1.4-5
[70] curl_4.3 R6_2.5.0 zoo_1.8-8
[73] dplyr_1.0.4 utf8_1.1.4 stringi_1.5.3
[76] Rcpp_1.0.6 vctrs_0.3.6 DEoptimR_1.0-8
[79] tidyselect_1.1.0 xfun_0.21 lmtest_0.9-38
Für Informationen zur Interpretation dieses Outputs schaut auch den Abschnitt Replizierbarkeit von Analysen des Kapitels zu Paketen an.