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?
No creo que quiera / pueda reemplazar con valores NULL, pero NA cumple ese propósito en Ringo.
Chase
Respuestas:
243
Sustitución de todos los ceros a NA:
df[df ==0]<-NA
Explicación
1. No es NULLlo 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 NAes 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, NULLvalores).
Ahora podría reemplazar ceros NULLen 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 NAy estableciendo el valor de usetan "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 == 0vectorización. df == 0devuelve (pruébelo) una matriz del mismo tamaño que df, con las entradas TRUEy 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] <- NAproduzca 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.
¿Cuál sería la sintaxis equivalente para un objeto data.table?
itpetersen
66
Veo que ha obtenido muchos votos, pero no creo que esto cubra adecuadamente los casos límite de columnas no numéricas con valores de "0" que no se solicitó que se establecieran en <NA>.
IRTFM
33
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
#Sample data
set.seed(1)
dat <- data.frame(x = sample(0:2,5,TRUE), y = sample(0:2,5,TRUE))#-----
x y
102212311421500#replace zeros with NA
dat[dat==0]<-NA#-----
x y
1NA22123114215NANA
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:11502:21163:31124:41115:5126:61127:7108:8109:121910:2240
status[N ==0, N :=NA]
head(status,10)
origin destination N
1:11502:21163:31124:41115:5126:61127:71NA8:81NA9:121910:2240
O for (j in names(DT)); set(DT,which(DT[[j]] == 0),j,NA). Vea aquí una discusión más detallada sobre el uso de data.table para buscar y reemplazar valores.
JWilliman
4
Puede reemplazar 0con NAsolo 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:5con el número de columnas en su marco de datos, o con 1:ncol(df).
No estoy seguro de que esta sea la solución correcta. ¿Qué pasa con las columnas 6 y más? Se cortarán.
userJT
Eso es por lo que sugirió reemplazar 1:5con 1:ncol(df)al final. No quería que la ecuación fuera demasiado compleja o difícil de leer.
Alium Britt
pero ¿qué pasa si en las columnas 6 y 7? el tipo de datos es char y no se debe hacer ningún reemplazo. En mi problema, necesito reemplazo solo en las columnas 12 a 15, pero todo el df tiene 21 columnas (muchas no deben tocarse en absoluto).
userJT
Para su trama de datos puede simplemente cambiar el 1:5que 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 }.
Alium Britt
0
En caso de que alguien llegue aquí a través de Google buscando lo contrario (es decir, cómo reemplazar todos los NA en un data.frame con 0), la respuesta es
Respuestas:
Sustitución de todos los ceros a NA:
Explicación
1. No es
NULL
lo que debe reemplazar con ceros. Como se dice en?'NULL'
,que es único y, supongo, puede verse como el objeto menos informativo y vacío. 1 Entonces no es tan sorprendente que
Es decir, R no reserva ningún espacio para este objeto nulo. 2 Mientras tanto, mirando
?'NA'
vemos queEs importante destacar que
NA
es de longitud 1, por lo que R le reserva algo de espacio. P.ej,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
, ocor
, que en realidad es equivalente a la sustitución de primera ceros conNA
y estableciendo el valor deuse
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 quedf
, con las entradasTRUE
yFALSE
. Además, también se nos permite pasar esta matriz al subconjunto[...]
(ver?'['
). Por último, si bien el resultadodf[df == 0]
es perfectamente intuitivo, puede parecer extraño quedf[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.
fuente
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
fuente
Una forma alternativa sin la
[<-
función:Un marco de datos de muestra
dat
(copiado descaradamente de la respuesta de @ Chase):Los ceros se pueden reemplazar
NA
por lais.na<-
función:fuente
dplyr::na_if()
es una opción:fuente
fuente
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]
fuente
for (j in names(DT)); set(DT,which(DT[[j]] == 0),j,NA)
. Vea aquí una discusión más detallada sobre el uso de data.table para buscar y reemplazar valores.Puede reemplazar
0
conNA
solo en campos numéricos (es decir, excluyendo cosas como factores), pero funciona columna por columna:Con una función, puede aplicar esto a todo su marco de datos:
Aunque podría reemplazar el
1:5
con el número de columnas en su marco de datos, o con1:ncol(df)
.fuente
1:5
con1: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 igual12: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 }
.En caso de que alguien llegue aquí a través de Google buscando lo contrario (es decir, cómo reemplazar todos los NA en un data.frame con 0), la respuesta es
O
Usando dplyr / tidyverse
fuente