NA significa "sconosciuto", e si diffonde
I dataset reali hanno dei buchi: la domanda del sondaggio lasciata in bianco, il sensore che ha perso una lettura. R rappresenta ogni buco con NA, not available. Il modello mentale cruciale: NA non è zero, non è una stringa vuota, non è un numero speciale. Significa "qui c'è un valore, ma non sappiamo quale sia."
Prendilo sul serio e il comportamento di R diventa logico. Quanto fa un numero sconosciuto più uno? Sconosciuto. Qual è la media di 4, 8 e qualcosa di sconosciuto? Sconosciuta: il valore mancante potrebbe essere qualsiasi cosa, quindi anche la media:
Tutti e tre stampano NA. Questo contagio è una caratteristica, non un bug: R si rifiuta di fingere in silenzio di conoscere una risposta che non conosce. Un foglio di calcolo che salta in silenzio le celle vuote può nascondere il fatto che manca metà di una colonna; R ti costringe ad accorgertene e a decidere cosa devono significare i valori mancanti per la tua analisi. Il resto dell'articolo parla di come prendere quella decisione in modo consapevole.
Verificare NA: is.na(), mai ==
Ecco la prima trappola in cui cadono tutti. Vuoi trovare i valori mancanti, quindi scrivi un confronto, e non funziona:
x == NA restituisce NA NA NA, nemmeno un TRUE. Perché? Segui la logica di "sconosciuto": 4 è uguale a un valore sconosciuto? Impossibile dirlo, perché lo sconosciuto potrebbe essere 4. Perfino la posizione con NA dà NA nel confronto: uno sconosciuto è uguale a un altro? Sconosciuto. Un confronto con NA non può mai restituire TRUE o FALSE, quindi come test è inutile, e peggio ancora, una maschera fatta solo di NA dentro [ ] non seleziona quello che ti aspetti.
Lo strumento corretto è is.na(), costruito apposta per rispondere a questa domanda, che restituisce valori logici onesti: FALSE TRUE FALSE. Da qui, due idiomi che userai di continuo:
sum(is.na(x)) conta i valori mancanti (TRUE vale 1 nella somma): eseguilo su ogni colonna di un nuovo dataset prima di qualsiasi altra cosa. which(is.na(x)) li localizza. E x[!is.na(x)] tiene solo i valori osservati: rimozione manuale tramite una maschera logica, il solito schema di filtraggio dei vettori.
Saltare NA nei riepiloghi: na.rm = TRUE
Di solito non serve rimuovere gli NA a mano, perché le funzioni di riepilogo di R hanno una via d'uscita integrata, l'argomento na.rm (NA remove):
Con na.rm = TRUE, la funzione scarta i valori mancanti e calcola su quello che resta: la media di 4 e 8 è 6. sum(), sd(), median(), min(), max(), var(): tutta la famiglia della statistica descrittiva lo accetta.
Nota che il default è FALSE. È R che prende posizione a tuo favore: vuole che ignorare i dati mancanti sia una scelta esplicita che metti per iscritto, non un default silenzioso. Quando scrivi na.rm = TRUE, stai affermando "qui i valori mancanti si possono ignorare senza rischi", il che è vero quando un sensore ha perso qualche lettura a caso, e pericolosamente falso quando, per esempio, chi guadagna meno ha saltato la domanda sul reddito. L'argomento ti fa assumere la responsabilità di quella scelta.
Eliminare le righe incomplete: na.omit() e complete.cases()
In un data frame i valori mancanti stanno nelle celle, ma l'analisi spesso lavora riga per riga, quindi l'operazione comune è eliminare le righe che hanno almeno un NA:
na.omit(df) restituisce il data frame senza ogni riga che contiene almeno un NA: qui sopravvive solo Rosa. complete.cases(df) restituisce la maschera logica delle righe (TRUE FALSE FALSE) dietro la stessa idea, e indicizzare con essa dà risultati identici con due vantaggi: puoi prima contare cosa stai per perdere (sum(!complete.cases(df))), e puoi limitare le colonne che contano: df[complete.cases(df[, "age"]), ] elimina solo le righe senza age, tenendo Mia anche se il suo punteggio è sconosciuto.
Quella forma limitata alle colonne conta più di quanto sembri: na.omit() su un data frame largo può scartare in silenzio la maggior parte delle righe a causa di NA in colonne che non avevi nemmeno intenzione di analizzare. Sappi quante righe stai eliminando, e perché, prima di eliminarle.
Sostituire NA
A volte la mossa giusta è riempire i buchi invece di cancellare righe. L'idioma combina is.na() con un'assegnazione:
Leggilo come: "nelle posizioni in cui visits manca, metti 0." È legittimo esattamente quando NA codifica un valore noto: un cliente senza alcun record di visite ha davvero fatto zero visite.
Ma sii onesto su quando è vero. Se NA significa "non siamo riusciti a misurarlo", sostituire con 0 fabbrica dati: rimpiazzare i punteggi mancanti di un test con 0 trascina giù la media come se quegli studenti avessero preso zero, quando in realtà non sai quanto hanno preso. Confronta la media qui sopra (2.4) con la media con na.rm dei dati originali (4): stessi dati, affermazioni diverse. Sostituire con la media o la mediana distorce meno, ma sottostima comunque la variabilità. La regola: imputa un valore solo quando sai dire, a parole semplici, perché quel valore è ciò che il dato mancante era davvero. Altrimenti tieni l'NA e usa na.rm: "sconosciuto" è spesso il valore più sincero del dataset.
NA, NULL, NaN e Inf a confronto
R ha quattro valori speciali che si somigliano ma significano cose davvero diverse:
| Valore | Significato | Lunghezza | Origine tipica |
|---|---|---|---|
NA | Un valore esiste ma è sconosciuto | 1 (occupa un posto) | Dati mancanti |
NULL | Nessun oggetto | 0 (nessun posto) | Elemento di lista eliminato, risultato vuoto |
NaN | Calcolo con risultato non definito | 1 | 0 / 0, log(-1) |
Inf | Un numero oltre la rappresentazione | 1 | 1 / 0, overflow |
Le distinzioni che contano nella pratica: NULL sparisce dentro i vettori (c(1, NULL, 3) ha due elementi, quindi non può rappresentare un'osservazione mancante), mentre NA mantiene il suo posto. NaN conta come mancante (is.na(NaN) è TRUE, quindi anche na.rm lo rimuove), ma non vale il contrario: is.nan(NA) è FALSE. E Inf non è mancante: è un numero vero e confrontabile (Inf > 1e300 è TRUE), quindi na.rm non lo rimuove; usa is.finite() per tenere solo i numeri ordinari.
Per completezza: NA esiste in silenzio in varie versioni tipizzate (NA_integer_, NA_real_, NA_character_) così può stare in qualsiasi vettore senza violare la regola del tipo unico. Le scriverai raramente, ma le vedrai nel codice dei pacchetti e nei messaggi di errore di dplyr.
Cosa ti porti a casa
NAsignifica "sconosciuto", e gli sconosciuti sono contagiosi: qualsiasi calcolo che tocca NA restituisce NA, per scelta di progetto.- Verifica con
is.na(), mai con== NA; conta i buchi consum(is.na(x)). na.rm = TRUEfa saltare gli NA alle funzioni di riepilogo: una decisione esplicita, chiamata per chiamata, che i valori mancanti si possono ignorare.na.omit()elimina in blocco le righe incomplete;complete.cases()ti dà la maschera, che puoi contare e limitare alle colonne che contano.- Sostituisci NA (
x[is.na(x)] <- value) solo quando puoi giustificare cosa fosse davvero il valore mancante. - NA ≠ NULL ≠ NaN ≠ Inf: valore mancante, oggetto assente, calcolo non definito, numero illimitato.
Prossimo passo: le funzioni, per impacchettare la tua logica in pezzi riutilizzabili e con un nome.
Domande frequenti
Perché mean() restituisce NA in R?
Perché almeno un valore del vettore è NA, e NA è contagioso: se un input è sconosciuto, R dice che anche la risposta è sconosciuta. Passa na.rm = TRUE, come in mean(x, na.rm = TRUE), per calcolare la media dei valori presenti. La maggior parte delle funzioni di riepilogo (sum, sd, median, min, max) accetta lo stesso argomento.
Come si controlla la presenza di NA in R?
Con is.na(x), che restituisce TRUE dove un valore manca. Non verificare mai con x == NA: confrontare qualcosa con un valore sconosciuto dà NA, non TRUE o FALSE, quindi il test fallisce in silenzio. sum(is.na(x)) conta i valori mancanti; which(is.na(x)) ne trova le posizioni.
Come si eliminano le righe con NA da un data frame in R?
na.omit(df) elimina ogni riga che contiene almeno un NA. Per avere più controllo, complete.cases(df) restituisce un vettore logico che segna le righe completamente osservate, quindi df[complete.cases(df), ] fa la stessa cosa in modo esplicito, e puoi applicarlo solo alle colonne che contano, per esempio df[complete.cases(df[, c("age", "score")]), ].
Qual è la differenza tra NA e NULL in R?
NA è un valore mancante: occupa un posto in un vettore e ha lunghezza 1. NULL è l'assenza di un oggetto: ha lunghezza 0 e sparisce quando lo metti in un vettore: c(1, NULL, 3) ha solo due elementi. Usa NA per un dato mancante; NULL compare quando rimuovi elementi da una lista o come valore restituito vuoto.