NA bedeutet "unbekannt" - und es breitet sich aus
Reale Datensätze haben Löcher: die unbeantwortete Umfragefrage, der Sensor, der eine Messung verpasst hat. R stellt jedes Loch mit NA dar - not available. Das entscheidende Denkmodell: NA ist nicht null, keine leere Zeichenkette, keine spezielle Zahl. Es bedeutet "hier gibt es einen Wert, aber wir wissen nicht, welchen."
Nimm das ernst, und R's Verhalten wird logisch. Was ist eine unbekannte Zahl plus eins? Unbekannt. Was ist der Durchschnitt von 4, 8 und etwas Unbekanntem? Unbekannt - der fehlende Wert könnte alles sein, also könnte der Mittelwert alles sein:
Alle drei geben NA aus. Diese Ansteckung ist ein Feature, kein Bug: R weigert sich, still so zu tun, als kenne es eine Antwort, die es nicht kennt. Eine Tabellenkalkulation, die Leerzellen still überspringt, kann verbergen, dass eine halbe Spalte fehlt; R zwingt dich, es zu bemerken und zu entscheiden, was fehlende Werte für deine Analyse bedeuten sollen. Der Rest dieses Artikels handelt davon, diese Entscheidung bewusst zu treffen.
Auf NA prüfen: is.na(), nie ==
Hier ist die erste Falle, in die jeder tappt. Du willst die fehlenden Werte finden, schreibst also einen Vergleich - und der funktioniert nicht:
x == NA gibt NA NA NA zurück - kein einziges TRUE. Warum? Folge der Logik von "unbekannt": Ist 4 gleich irgendeinem unbekannten Wert? Nicht sagbar - das Unbekannte könnte 4 sein. Selbst der NA-Platz vergleicht sich als NA: Ist ein Unbekanntes gleich einem anderen? Unbekannt. Ein Vergleich mit NA kann nie TRUE oder FALSE liefern, als Test ist er also nutzlos - und schlimmer noch, eine reine NA-Maske in [ ] wählt nicht das aus, was du erwartest.
Das korrekte Werkzeug ist is.na(), gebaut, um genau diese Frage zu beantworten, und es gibt ehrliche Logicals zurück: FALSE TRUE FALSE. Von dort aus zwei Idiome, die du ständig nutzen wirst:
sum(is.na(x)) zählt die fehlenden Werte (TRUE summiert als 1) - führ es auf jeder Spalte eines neuen Datensatzes aus, bevor du irgendetwas anderes tust. which(is.na(x)) findet sie. Und x[!is.na(x)] behält nur die beobachteten Werte - manuelles Entfernen über eine logische Maske, dasselbe Vektor-Filtermuster wie immer.
NA in Zusammenfassungen überspringen: na.rm = TRUE
Meist musst du NAs nicht von Hand entfernen, denn R's Zusammenfassungsfunktionen haben eine eingebaute Notluke - das Argument na.rm (NA remove):
Mit na.rm = TRUE verwirft die Funktion die fehlenden Werte und rechnet mit dem Rest: Der Mittelwert von 4 und 8 ist 6. sum(), sd(), median(), min(), max(), var() - die ganze Familie der deskriptiven Statistik akzeptiert es.
Beachte, dass die Voreinstellung FALSE ist. Das ist R, das eine Meinung zu deinen Gunsten hat: Das Ignorieren fehlender Daten soll eine ausdrückliche Entscheidung sein, die du hinschreibst, keine stille Voreinstellung. Wenn du na.rm = TRUE tippst, behauptest du "die fehlenden Werte kann man hier gefahrlos ignorieren" - was stimmt, wenn ein Sensor zufällig ein paar Messungen verpasst hat, und gefährlich falsch ist, wenn etwa die Geringverdiener die Einkommensfrage übersprungen haben. Das Argument zwingt dich, diese Entscheidung zu verantworten.
Unvollständige Zeilen entfernen: na.omit() und complete.cases()
In einem Data Frame sitzt Fehlendes in Zellen, aber Analysen arbeiten oft zeilenweise - deshalb ist die übliche Operation das Entfernen von Zeilen mit irgendeinem NA:
na.omit(df) gibt den Data Frame ohne jede Zeile zurück, die mindestens ein NA enthält - hier überlebt nur Rosa. complete.cases(df) gibt die logische Zeilenmaske (TRUE FALSE FALSE) hinter derselben Idee zurück, und die Indexierung damit liefert identische Ergebnisse mit zwei Vorteilen: Du kannst vorher zählen, was du verlieren wirst (sum(!complete.cases(df))), und du kannst einschränken, welche Spalten zählen - df[complete.cases(df[, "age"]), ] entfernt nur Zeilen ohne age und behält Mia, obwohl ihre Punktzahl unbekannt ist.
Diese spaltenbeschränkte Form ist wichtiger, als sie aussieht: na.omit() auf einem breiten Data Frame kann wegen NAs in Spalten, die du nie analysieren wolltest, still den Großteil deiner Zeilen verwerfen. Wisse, wie viele Zeilen du entfernst und warum, bevor du sie entfernst.
NA ersetzen
Manchmal ist der richtige Zug, Löcher zu füllen, statt Zeilen zu löschen. Das Idiom kombiniert is.na() mit einer Zuweisung:
Lies es als: "In den Plätzen, wo visits fehlt, setze 0." Das ist genau dann legitim, wenn NA einen bekannten Wert codiert - eine Kundin ohne Besuchsdatensatz hatte tatsächlich null Besuche.
Aber sei ehrlich, wann das zutrifft. Bedeutet NA "wir konnten es nicht messen", erfindet das Ersetzen durch 0 Daten: Fehlende Testergebnisse durch 0 zu ersetzen zieht den Mittelwert herunter, als hätten diese Studierenden null Punkte erzielt, während du in Wahrheit nicht weißt, was sie erzielt haben. Vergleiche den Mittelwert oben (2,4) mit dem na.rm-Mittelwert des Originals (4): dieselben Daten, andere Aussagen. Das Ersetzen durch Mittelwert oder Median verzerrt weniger, unterschätzt aber weiterhin die Streuung. Die Regel: Imputiere einen Wert nur, wenn du in klaren Worten sagen kannst, warum dieser Wert das ist, was der fehlende Eintrag wirklich war. Sonst behalte das NA und nutze na.rm - "unbekannt" ist oft der wahrhaftigste Wert im Datensatz.
NA vs. NULL vs. NaN vs. Inf
R hat vier ähnlich aussehende Sonderwerte, die wirklich Verschiedenes bedeuten:
| Wert | Bedeutung | Länge | Typische Quelle |
|---|---|---|---|
NA | Ein Wert existiert, ist aber unbekannt | 1 (belegt einen Platz) | Fehlende Daten |
NULL | Überhaupt kein Objekt | 0 (kein Platz) | Gelöschtes Listenelement, leeres Ergebnis |
NaN | Rechnung mit undefiniertem Ergebnis | 1 | 0 / 0, log(-1) |
Inf | Eine Zahl jenseits der Darstellbarkeit | 1 | 1 / 0, Überlauf |
Die praktisch wichtigen Unterschiede: NULL verschwindet in Vektoren (c(1, NULL, 3) hat zwei Elemente - es kann keine fehlende Beobachtung darstellen), während NA seinen Platz behält. NaN zählt als fehlend (is.na(NaN) ist TRUE, also entfernt na.rm es ebenfalls), aber umgekehrt gilt das nicht - is.nan(NA) ist FALSE. Und Inf ist nicht fehlend - es ist eine echte, vergleichbare Zahl (Inf > 1e300 ist TRUE), also entfernt na.rm es nicht; nutze is.finite(), um auf gewöhnliche Zahlen zu filtern.
Der Vollständigkeit halber: NA kommt still in typisierten Varianten (NA_integer_, NA_real_, NA_character_), damit es in jedem Vektor sitzen kann, ohne die Ein-Typ-Regel zu brechen. Du wirst sie selten tippen, aber in Paketcode und dplyr-Fehlermeldungen sehen.
Was du mitnimmst
NAbedeutet "unbekannt", und Unbekanntes ist ansteckend: Jede Berechnung, die NA berührt, gibt NA zurück - so gewollt.- Prüfe mit
is.na(), nie mit== NA; zähle Löcher mitsum(is.na(x)). na.rm = TRUElässt Zusammenfassungsfunktionen NAs überspringen - eine ausdrückliche Entscheidung pro Aufruf, dass die fehlenden Werte ignorierbar sind.na.omit()entfernt unvollständige Zeilen pauschal;complete.cases()gibt dir die Maske, zählbar und auf die relevanten Spalten beschränkbar.- Ersetze NA (
x[is.na(x)] <- value) nur, wenn du begründen kannst, was der fehlende Wert wirklich war. - NA ≠ NULL ≠ NaN ≠ Inf: fehlender Wert, abwesendes Objekt, undefinierte Rechnung, unbeschränkte Zahl.
Als Nächstes: Funktionen - deine Logik in wiederverwendbare, benannte Bausteine verpacken.
Häufig gestellte Fragen
Warum gibt mean() in R NA zurück?
Weil mindestens ein Wert im Vektor NA ist und NA ansteckend wirkt: Ist irgendeine Eingabe unbekannt, sagt R, dass auch die Antwort unbekannt ist. Übergib na.rm = TRUE - mean(x, na.rm = TRUE) -, um den Mittelwert der vorhandenen Werte zu berechnen. Die meisten Zusammenfassungsfunktionen (sum, sd, median, min, max) akzeptieren dasselbe Argument.
Wie prüft man in R auf NA?
Mit is.na(x), das überall dort TRUE zurückgibt, wo ein Wert fehlt. Prüfe nie mit x == NA - irgendetwas mit einem Unbekannten zu vergleichen ergibt NA, nicht TRUE oder FALSE, sodass der Test still scheitert. sum(is.na(x)) zählt die fehlenden Werte; which(is.na(x)) findet ihre Positionen.
Wie entfernt man in R Zeilen mit NA aus einem Data Frame?
na.omit(df) entfernt jede Zeile, die mindestens ein NA enthält. Für mehr Kontrolle gibt complete.cases(df) einen logischen Vektor zurück, der vollständig beobachtete Zeilen markiert, sodass df[complete.cases(df), ] dasselbe explizit tut - und du kannst es auf genau die Spalten anwenden, die zählen, z. B. df[complete.cases(df[, c("age", "score")]), ].
Was ist der Unterschied zwischen NA und NULL in R?
NA ist ein fehlender Wert - es belegt einen Platz in einem Vektor und hat Länge 1. NULL ist die Abwesenheit eines Objekts - es hat Länge 0 und verschwindet, wenn man es in einen Vektor steckt: c(1, NULL, 3) hat nur zwei Elemente. Nutze NA für einen fehlenden Datenpunkt; NULL taucht beim Entfernen von Listenelementen oder als leerer Rückgabewert auf.