Ho un dataframe con alcune colonne numeriche. Alcune righe hanno un valore 0 che deve essere considerato nullo nell'analisi statistica. Qual è il modo più veloce per sostituire tutto il valore 0 in NULL in R?
Ho un dataframe con alcune colonne numeriche. Alcune righe hanno un valore 0 che deve essere considerato nullo nell'analisi statistica. Qual è il modo più veloce per sostituire tutto il valore 0 in NULL in R?
Risposte:
Sostituzione di tutti gli zeri in NA:
df[df == 0] <- NA
Spiegazione
1. Non è NULL
quello con cui dovresti sostituire gli zeri. Come dice in ?'NULL'
,
NULL rappresenta l'oggetto null in R
che è unico e, immagino, può essere visto come l'oggetto più disinformativo e vuoto. 1 Quindi non è così sorprendente
data.frame(x = c(1, NULL, 2))
# x
# 1 1
# 2 2
Cioè, R non riserva spazio per questo oggetto null. 2 Nel frattempo, guardando ?'NA'
lo vediamo
NA è una costante logica di lunghezza 1 che contiene un indicatore di valore mancante. NA può essere forzato su qualsiasi altro tipo di vettore ad eccezione di raw.
È importante sottolineare che NA
è di lunghezza 1 in modo che R riservi un po 'di spazio per esso. Per esempio,
data.frame(x = c(1, NA, 2))
# x
# 1 1
# 2 NA
# 3 2
Inoltre, la struttura del frame di dati richiede che tutte le colonne abbiano lo stesso numero di elementi in modo che non possano esserci "buchi" (ovvero NULL
valori).
Ora è possibile sostituire gli zero NULL
in un frame di dati, nel senso di rimuovere completamente tutte le righe contenenti almeno uno zero. Quando si utilizza, ad esempio, var
, cov
, o cor
, che in realtà è equivalente alla sostituzione prima zeri con NA
e impostando il valore di use
come "complete.obs"
. In genere, tuttavia, ciò non è soddisfacente in quanto comporta una perdita di informazioni aggiuntiva.
2. Invece di eseguire una sorta di ciclo, nella soluzione utilizzo la df == 0
vettorializzazione. df == 0
restituisce (provalo) una matrice delle stesse dimensioni di df
, con le voci TRUE
e FALSE
. Inoltre, ci è anche permesso di passare questa matrice al sottoinsieme [...]
(vedi ?'['
). Infine, mentre il risultato di df[df == 0]
è perfettamente intuitivo, può sembrare strano che df[df == 0] <- NA
dia l'effetto desiderato. In <-
effetti, l' operatore di assegnazione non è sempre così intelligente e non funziona in questo modo con alcuni altri oggetti, ma lo fa con i frame di dati; vedi ?'<-'
.
1 L'insieme vuoto nella teoria dell'insieme sembra in qualche modo correlato.
2 Un'altra somiglianza con la teoria degli insiemi: l'insieme vuoto è un sottoinsieme di ogni insieme, ma non ci riserviamo spazio.
Suppongo che data.frame sia un mix di tipi di dati diversi e non tutte le colonne debbano essere modificate.
per modificare solo le colonne da 12 a 18 (del totale 21), basta fare questo
df[, 12:18][df[, 12:18] == 0] <- NA
Un modo alternativo senza la [<-
funzione:
Un frame di dati di esempio dat
(copiato spudoratamente dalla risposta di @ Chase):
dat
x y
1 0 2
2 1 2
3 1 1
4 2 1
5 0 0
Gli zeri possono essere sostituiti con NA
la is.na<-
funzione:
is.na(dat) <- !dat
dat
x y
1 NA 2
2 1 2
3 1 1
4 2 1
5 NA NA
Poiché qualcuno ha richiesto la versione Data.Table di ciò e poiché la soluzione data.frame fornita non funziona con data.table, sto fornendo la soluzione di seguito.
Fondamentalmente, utilizzare l' :=
operatore ->DT[x == 0, x := NA]
library("data.table")
status = as.data.table(occupationalStatus)
head(status, 10)
origin destination N
1: 1 1 50
2: 2 1 16
3: 3 1 12
4: 4 1 11
5: 5 1 2
6: 6 1 12
7: 7 1 0
8: 8 1 0
9: 1 2 19
10: 2 2 40
status[N == 0, N := NA]
head(status, 10)
origin destination N
1: 1 1 50
2: 2 1 16
3: 3 1 12
4: 4 1 11
5: 5 1 2
6: 6 1 12
7: 7 1 NA
8: 8 1 NA
9: 1 2 19
10: 2 2 40
for (j in names(DT)); set(DT,which(DT[[j]] == 0),j,NA)
. Vedi qui per una discussione più dettagliata sull'uso di data.table per trovare e sostituire i valori.
Puoi sostituirlo 0
con NA
solo nei campi numerici (cioè escludendo cose come i fattori), ma funziona su una colonna per colonna:
col[col == 0 & is.numeric(col)] <- NA
Con una funzione, puoi applicarlo a tutto il tuo frame di dati:
changetoNA <- function(colnum,df) {
col <- df[,colnum]
if (is.numeric(col)) { #edit: verifying column is numeric
col[col == -1 & is.numeric(col)] <- NA
}
return(col)
}
df <- data.frame(sapply(1:5, changetoNA, df))
Sebbene sia possibile sostituire il 1:5
con il numero di colonne nel frame di dati o con 1:ncol(df)
.
1:5
con 1:ncol(df)
alla fine. Non volevo rendere l'equazione troppo complessa o difficile da leggere.
1:5
ai numeri colonna che si desidera modificati, come 12:15
, ma se si voleva confermare che interesserà solo le colonne numeriche poi basta avvolgere la seconda linea della funzione in un'istruzione if, come questo: if (is.numeric(col)) { col[col == -1 & is.numeric(col)] <- NA }
.