Tengo un marco de datos con algunas columnas numéricas. Algunas filas tienen un valor 0 que debe considerarse nulo en el análisis estadístico. ¿Cuál es la forma más rápida de reemplazar todo el valor 0 a NULL en R?
Tengo un marco de datos con algunas columnas numéricas. Algunas filas tienen un valor 0 que debe considerarse nulo en el análisis estadístico. ¿Cuál es la forma más rápida de reemplazar todo el valor 0 a NULL en R?
Respuestas:
Sustitución de todos los ceros a NA:
df[df == 0] <- NA
Explicación
1. No es NULL
lo que debe reemplazar con ceros. Como se dice en ?'NULL'
,
NULL representa el objeto nulo en R
que es único y, supongo, puede verse como el objeto menos informativo y vacío. 1 Entonces no es tan sorprendente que
data.frame(x = c(1, NULL, 2))
# x
# 1 1
# 2 2
Es decir, R no reserva ningún espacio para este objeto nulo. 2 Mientras tanto, mirando ?'NA'
vemos que
NA es una constante lógica de longitud 1 que contiene un indicador de valor faltante. NA puede ser coaccionado a cualquier otro tipo de vector excepto raw.
Es importante destacar que NA
es de longitud 1, por lo que R le reserva algo de espacio. P.ej,
data.frame(x = c(1, NA, 2))
# x
# 1 1
# 2 NA
# 3 2
Además, la estructura del marco de datos requiere que todas las columnas tengan el mismo número de elementos para que no pueda haber "agujeros" (es decir, NULL
valores).
Ahora podría reemplazar ceros NULL
en un marco de datos en el sentido de eliminar completamente todas las filas que contienen al menos un cero. Cuando se utiliza, por ejemplo, var
, cov
, o cor
, que en realidad es equivalente a la sustitución de primera ceros con NA
y estableciendo el valor de use
tan "complete.obs"
. Por lo general, sin embargo, esto no es satisfactorio, ya que conduce a la pérdida de información adicional.
2. En lugar de ejecutar algún tipo de bucle, en la solución uso la df == 0
vectorización. df == 0
devuelve (pruébelo) una matriz del mismo tamaño que df
, con las entradas TRUE
y FALSE
. Además, también se nos permite pasar esta matriz al subconjunto [...]
(ver ?'['
). Por último, si bien el resultado df[df == 0]
es perfectamente intuitivo, puede parecer extraño que df[df == 0] <- NA
produzca el efecto deseado. De <-
hecho, el operador de asignación no siempre es tan inteligente y no funciona de esta manera con otros objetos, pero lo hace con marcos de datos; ver ?'<-'
.
1 El conjunto vacío en la teoría de conjuntos se siente de alguna manera relacionado.
2 Otra similitud con la teoría de conjuntos: el conjunto vacío es un subconjunto de cada conjunto, pero no le reservamos ningún espacio.
Déjame asumir que tu data.frame es una mezcla de diferentes tipos de datos y no todas las columnas necesitan ser modificadas.
para modificar solo las columnas 12 a 18 (del total de 21), solo haga esto
df[, 12:18][df[, 12:18] == 0] <- NA
Una forma alternativa sin la [<-
función:
Un marco de datos de muestra dat
(copiado descaradamente de la respuesta de @ Chase):
dat
x y
1 0 2
2 1 2
3 1 1
4 2 1
5 0 0
Los ceros se pueden reemplazar NA
por la is.na<-
función:
is.na(dat) <- !dat
dat
x y
1 NA 2
2 1 2
3 1 1
4 2 1
5 NA NA
#Sample data
set.seed(1)
dat <- data.frame(x = sample(0:2, 5, TRUE), y = sample(0:2, 5, TRUE))
#-----
x y
1 0 2
2 1 2
3 1 1
4 2 1
5 0 0
#replace zeros with NA
dat[dat==0] <- NA
#-----
x y
1 NA 2
2 1 2
3 1 1
4 2 1
5 NA NA
Debido a que alguien solicitó la versión Data.Table de esto, y porque la solución data.frame dada no funciona con data.table, proporciono la solución a continuación.
Básicamente, use el :=
operador ->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
Puede reemplazar 0
con NA
solo en campos numéricos (es decir, excluyendo cosas como factores), pero funciona columna por columna:
col[col == 0 & is.numeric(col)] <- NA
Con una función, puede aplicar esto a todo su marco de datos:
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))
Aunque podría reemplazar el 1:5
con el número de columnas en su marco de datos, o con 1:ncol(df)
.
1:5
con 1:ncol(df)
al final. No quería que la ecuación fuera demasiado compleja o difícil de leer.
1:5
que los números de las columnas que quieren cambiar, al igual 12:15
, pero si quería que confirmar que sólo afectará a las columnas numéricas a continuación, sólo envolver la segunda línea de la función en una sentencia if, como esto: if (is.numeric(col)) { col[col == -1 & is.numeric(col)] <- NA }
.