with valores valor una reemplazar por faltantes datos data columna cambiar r dataframe na

valores - replace na with 0 in r



¿Cómo reemplazo los valores de NA con ceros en un marco de datos R? (14)

Con dplyr 0.5.0, puede usar la función coalesce que puede integrarse fácilmente en %>% pipeline haciendo coalesce(vec, 0) . Esto reemplaza todas las NA en vec con 0:

Digamos que tenemos un marco de datos con NA s:

library(dplyr) df <- data.frame(v = c(1, 2, 3, NA, 5, 6, 8)) df # v # 1 1 # 2 2 # 3 3 # 4 NA # 5 5 # 6 6 # 7 8 df %>% mutate(v = coalesce(v, 0)) # v # 1 1 # 2 2 # 3 3 # 4 0 # 5 5 # 6 6 # 7 8

Tengo un marco de datos y algunas columnas tienen valores de NA .

¿Cómo puedo reemplazar estos valores de NA con ceros?


Enfoque más general del uso de replace() en matriz o vector para reemplazar NA a 0

Por ejemplo:

> x <- c(1,2,NA,NA,1,1) > x1 <- replace(x,is.na(x),0) > x1 [1] 1 2 0 0 1 1

Esta es también una alternativa al uso de ifelse() en dplyr

df = data.frame(col = c(1,2,NA,NA,1,1)) df <- df %>% mutate(col = replace(col,is.na(col),0))


Esta simple función extraída de Datacamp podría ayudar:

replace_missings <- function(x, replacement) { is_miss <- is.na(x) x[is_miss] <- replacement message(sum(is_miss), " missings replaced by the value ", replacement) x }

Entonces

replace_missings(df, replacement = 0)


Hubiera comentado en la publicación de @ianmunoz pero no tengo suficiente reputación. Puede combinar dplyr y replace mutate_each para ocuparse del replace de NA a 0 . Usando el marco de datos de la respuesta de @ aL3xa ...

> m <- matrix(sample(c(NA, 1:10), 100, replace = TRUE), 10) > d <- as.data.frame(m) > d V1 V2 V3 V4 V5 V6 V7 V8 V9 V10 1 4 8 1 9 6 9 NA 8 9 8 2 8 3 6 8 2 1 NA NA 6 3 3 6 6 3 NA 2 NA NA 5 7 7 4 10 6 1 1 7 9 1 10 3 10 5 10 6 7 10 10 3 2 5 4 6 6 2 4 1 5 7 NA NA 8 4 4 7 7 2 3 1 4 10 NA 8 7 7 8 9 5 8 10 5 3 5 8 3 2 9 9 1 8 7 6 5 NA NA 6 7 10 6 10 8 7 1 1 2 2 5 7 > d %>% mutate_each( funs_( interp( ~replace(., is.na(.),0) ) ) ) V1 V2 V3 V4 V5 V6 V7 V8 V9 V10 1 4 8 1 9 6 9 0 8 9 8 2 8 3 6 8 2 1 0 0 6 3 3 6 6 3 0 2 0 0 5 7 7 4 10 6 1 1 7 9 1 10 3 10 5 10 6 7 10 10 3 2 5 4 6 6 2 4 1 5 7 0 0 8 4 4 7 7 2 3 1 4 10 0 8 7 7 8 9 5 8 10 5 3 5 8 3 2 9 9 1 8 7 6 5 0 0 6 7 10 6 10 8 7 1 1 2 2 5 7

Estamos utilizando la evaluación estándar (SE) aquí, por lo que necesitamos el guión bajo en " funs_ ". También usamos el interp / ~ interp y el . hace referencia a "todo con lo que estamos trabajando", es decir, el marco de datos. Ahora hay ceros!


La opción híbrida dplyr / Base R : mutate_all(funs(replace(., is.na(.), 0)))) es más del doble de rápida que la base R d[is.na(d)] <- 0 opción. (Consulte los análisis de referencia a continuación.)

Si tiene dificultades con los marcos de datos masivos, data.table es la opción más rápida de todas: un 30% menos que dplyr y 3 veces más rápido de lo que se aproxima a la Base R. También modifica los datos en su lugar, lo que le permite trabajar con casi el doble de datos a la vez.

Un agrupamiento de otros enfoques útiles de reemplazo tidyverse

Ubicación:

  • index mutate_at(c(5:10), funs(replace(., is.na(.), 0)))
  • referencia directa mutate_at(vars(var5:var10), funs(replace(., is.na(.), 0)))
  • coincidencia fija mutate_at(vars(contains("1")), funs(replace(., is.na(.), 0)))
    • o en lugar de contains() , pruebe ends_with() , starts_with()
  • patrón coincidencia mutate_at(vars(matches("//d{2}")), funs(replace(., is.na(.), 0)))

Condicionalmente
(cambie solo numérico (columnas) y deje la cadena (columnas) solo).

  • enteros mutate_if(is.integer, funs(replace(., is.na(.), 0)))
  • duplica mutate_if(is.numeric, funs(replace(., is.na(.), 0)))
  • cadenas mutate_if(is.character, funs(replace(., is.na(.), 0)))

El análisis completo -

Enfoques probados:

# Base R: baseR.sbst.rssgn <- function(x) { x[is.na(x)] <- 0; x } baseR.replace <- function(x) { replace(x, is.na(x), 0) } baseR.for <- function(x) { for(j in 1:ncol(x)) x[[j]][is.na(x[[j]])] = 0 } # tidyverse ## dplyr library(tidyverse) dplyr_if_else <- function(x) { mutate_all(x, funs(if_else(is.na(.), 0, .))) } dplyr_coalesce <- function(x) { mutate_all(x, funs(coalesce(., 0))) } ## tidyr tidyr_replace_na <- function(x) { replace_na(x, as.list(setNames(rep(0, 10), as.list(c(paste0("var", 1:10)))))) } ## hybrid hybrd.ifelse <- function(x) { mutate_all(x, funs(ifelse(is.na(.), 0, .))) } hybrd.rplc_all <- function(x) { mutate_all(x, funs(replace(., is.na(.), 0))) } hybrd.rplc_at.idx<- function(x) { mutate_at(x, c(1:10), funs(replace(., is.na(.), 0))) } hybrd.rplc_at.nse<- function(x) { mutate_at(x, vars(var1:var10), funs(replace(., is.na(.), 0))) } hybrd.rplc_at.stw<- function(x) { mutate_at(x, vars(starts_with("var")), funs(replace(., is.na(.), 0))) } hybrd.rplc_at.ctn<- function(x) { mutate_at(x, vars(contains("var")), funs(replace(., is.na(.), 0))) } hybrd.rplc_at.mtc<- function(x) { mutate_at(x, vars(matches("//d+")), funs(replace(., is.na(.), 0))) } hybrd.rplc_if <- function(x) { mutate_if(x, is.numeric, funs(replace(., is.na(.), 0))) } # data.table library(data.table) DT.for.set.nms <- function(x) { for (j in names(x)) set(x,which(is.na(x[[j]])),j,0) } DT.for.set.sqln <- function(x) { for (j in seq_len(ncol(x))) set(x,which(is.na(x[[j]])),j,0) }

El código para este análisis:

library(microbenchmark) # 20% NA filled dataframe of 5 Million rows and 10 columns set.seed(42) # to recreate the exact dataframe dfN <- as.data.frame(matrix(sample(c(NA, as.numeric(1:4)), 5e6*10, replace = TRUE), dimnames = list(NULL, paste0("var", 1:10)), ncol = 10)) # Running 250 trials with each replacement method # (the functions are excecuted locally - so that the original dataframe remains unmodified in all cases) perf_results <- microbenchmark( hybrid.ifelse = hybrid.ifelse(copy(dfN)), dplyr_if_else = dplyr_if_else(copy(dfN)), baseR.sbst.rssgn = baseR.sbst.rssgn(copy(dfN)), baseR.replace = baseR.replace(copy(dfN)), dplyr_coalesce = dplyr_coalesce(copy(dfN)), hybrd.rplc_at.nse= hybrd.rplc_at.nse(copy(dfN)), hybrd.rplc_at.stw= hybrd.rplc_at.stw(copy(dfN)), hybrd.rplc_at.ctn= hybrd.rplc_at.ctn(copy(dfN)), hybrd.rplc_at.mtc= hybrd.rplc_at.mtc(copy(dfN)), hybrd.rplc_at.idx= hybrd.rplc_at.idx(copy(dfN)), hybrd.rplc_if = hybrd.rplc_if(copy(dfN)), tidyr_replace_na = tidyr_replace_na(copy(dfN)), baseR.for = baseR.for(copy(dfN)), DT.for.set.nms = DT.for.set.nms(copy(dfN)), DT.for.set.sqln = DT.for.set.sqln(copy(dfN)), times = 250L )

Resumen de Resultados

> perf_results Unit: milliseconds expr min lq mean median uq max neval hybrid.ifelse 5250.5259 5620.8650 5809.1808 5759.3997 5947.7942 6732.791 250 dplyr_if_else 3209.7406 3518.0314 3653.0317 3620.2955 3746.0293 4390.888 250 baseR.sbst.rssgn 1611.9227 1878.7401 1964.6385 1942.8873 2031.5681 2485.843 250 baseR.replace 1559.1494 1874.7377 1946.2971 1920.8077 2002.4825 2516.525 250 dplyr_coalesce 949.7511 1231.5150 1279.3015 1288.3425 1345.8662 1624.186 250 hybrd.rplc_at.nse 735.9949 871.1693 1016.5910 1064.5761 1104.9590 1361.868 250 hybrd.rplc_at.stw 704.4045 887.4796 1017.9110 1063.8001 1106.7748 1338.557 250 hybrd.rplc_at.ctn 723.9838 878.6088 1017.9983 1063.0406 1110.0857 1296.024 250 hybrd.rplc_at.mtc 686.2045 885.8028 1013.8293 1061.2727 1105.7117 1269.949 250 hybrd.rplc_at.idx 696.3159 880.7800 1003.6186 1038.8271 1083.1932 1309.635 250 hybrd.rplc_if 705.9907 889.7381 1000.0113 1036.3963 1083.3728 1338.190 250 tidyr_replace_na 680.4478 973.1395 978.2678 1003.9797 1051.2624 1294.376 250 baseR.for 670.7897 965.6312 983.5775 1001.5229 1052.5946 1206.023 250 DT.for.set.nms 496.8031 569.7471 695.4339 623.1086 861.1918 1067.640 250 DT.for.set.sqln 500.9945 567.2522 671.4158 623.1454 764.9744 1033.463 250

Diagrama de caja de resultados (en una escala de registro)

# adjust the margins to prepare for better boxplot printing par(mar=c(8,5,1,1) + 0.1) # generate boxplot boxplot(opN, las = 2, xlab = "", ylab = "log(time)[milliseconds]")

Diagrama de dispersión codificado por colores de ensayos (en una escala de registro)

qplot(y=time/10^9, data=opN, colour=expr) + labs(y = "log10 Scaled Elapsed Time per Trial (secs)", x = "Trial Number") + scale_y_log10(breaks=c(1, 2, 4))

Una nota sobre los otros artistas de alto rendimiento.

Cuando los conjuntos de datos se hacen más grandes, el reemplazo de Tidyr ''históricamente se había retirado al frente. Con la colección actual de 50M puntos de datos para ejecutar, se desempeña casi exactamente igual que la Base R For Loop. Tengo curiosidad por ver qué sucede con los marcos de datos de diferentes tamaños.

_all se pueden encontrar ejemplos adicionales para las variantes de función mutate y summarize _at y _all : https://rdrr.io/cran/dplyr/man/summarise_all.html Además, encontré demostraciones y colecciones de ejemplos útiles aquí: https://blog.exploratory.io/dplyr-0-5-is-awesome-heres-why-be095fd4eb8a

Atribuciones y apreciaciones

Con un agradecimiento especial a:

  • Tyler Rinker y Akrun por demostrar microbenchmark.
  • alexis_laz por trabajar para ayudarme a entender el uso de local() y (con la ayuda del paciente de Frank también) el papel que desempeña la coacción silenciosa en la aceleración de muchos de estos enfoques.
  • ArthurYip para el empuje para agregar la nueva función coalesce() y actualizar el análisis.
  • Gregor por el empujón para averiguar la data.table funciona lo suficientemente bien como para incluirlos finalmente en la alineación.
  • Base R Para loop: alexis_laz
  • data.table For Loops: Matt_Dowle

(Por supuesto, acércate y dales el voto positivo, también si encuentras útiles esos enfoques).

Nota sobre mi uso de Numerics: si tiene un conjunto de datos entero puro, todas sus funciones se ejecutarán más rápido. Por favor, vea alexis_laz para más información. IRL, no recuerdo haber encontrado un conjunto de datos que contenga más del 10-15% de enteros, por lo que estoy ejecutando estas pruebas en marcos de datos totalmente numéricos.


Otra opción compatible con dplyr pipe con el método replace_na que funciona para varias columnas:

require(dplyr) require(tidyr) m <- matrix(sample(c(NA, 1:10), 100, replace = TRUE), 10) d <- as.data.frame(m) myList <- setNames(lapply(vector("list", ncol(d)), function(x) x <- 0), names(d)) df <- d %>% replace_na(myList)

Puede restringir fácilmente, por ejemplo, a columnas numéricas:

d$str <- c("string", NA) myList <- myList[sapply(d, is.numeric)] df <- d %>% replace_na(myList)


Otro ejemplo usando el paquete imputeTS :

library(imputeTS) na.replace(yourDataframe, 0)


Para un solo vector:

x <- c(1,2,NA,4,5) x[is.na(x)] <- 0

Para un data.frame, haga una función de lo anterior, luego apply a las columnas.

Proporcione un ejemplo reproducible la próxima vez como se detalla aquí:

¿Cómo hacer un gran ejemplo reproducible de R?


Puedes usar replace()

Por ejemplo:

> x <- c(-1,0,1,0,NA,0,1,1) > x1 <- replace(x,5,1) > x1 [1] -1 0 1 0 1 0 1 1 > x1 <- replace(x,5,mean(x,na.rm=T)) > x1 [1] -1.00 0.00 1.00 0.00 0.29 0.00 1.00 1.00


Sé que la pregunta ya está respondida, pero hacerlo de esta manera podría ser más útil para algunos:

Define esta función:

na.zero <- function (x) { x[is.na(x)] <- 0 return(x) }

Ahora, cuando necesites convertir NA en un vector a cero, puedes hacer:

na.zero(some.vector)


Si desea reemplazar NA en variables de factor, esto podría ser útil:

n <- length(levels(data.vector))+1 data.vector <- as.numeric(data.vector) data.vector[is.na(data.vector)] <- n data.vector <- as.factor(data.vector) levels(data.vector) <- c("level1","level2",...,"leveln", "NAlevel")

Transforma un vector factorial en un vector numérico y agrega otro nivel de factor numérico artificial, que luego se transforma nuevamente en un vector factorial con un "nivel de NA" adicional de su elección.


Si intentamos reemplazar los NA al exportar, por ejemplo, al escribir en csv, podemos usar:

write.csv(data, "data.csv", na = "0")


Ver mi comentario en @ gsk3 respuesta. Un ejemplo simple:

> m <- matrix(sample(c(NA, 1:10), 100, replace = TRUE), 10) > d <- as.data.frame(m) V1 V2 V3 V4 V5 V6 V7 V8 V9 V10 1 4 3 NA 3 7 6 6 10 6 5 2 9 8 9 5 10 NA 2 1 7 2 3 1 1 6 3 6 NA 1 4 1 6 4 NA 4 NA 7 10 2 NA 4 1 8 5 1 2 4 NA 2 6 2 6 7 4 6 NA 3 NA NA 10 2 1 10 8 4 7 4 4 9 10 9 8 9 4 10 NA 8 5 8 3 2 1 4 5 9 4 7 9 3 9 10 1 9 9 10 5 3 3 10 4 2 2 5 NA 9 7 2 5 5 > d[is.na(d)] <- 0 > d V1 V2 V3 V4 V5 V6 V7 V8 V9 V10 1 4 3 0 3 7 6 6 10 6 5 2 9 8 9 5 10 0 2 1 7 2 3 1 1 6 3 6 0 1 4 1 6 4 0 4 0 7 10 2 0 4 1 8 5 1 2 4 0 2 6 2 6 7 4 6 0 3 0 0 10 2 1 10 8 4 7 4 4 9 10 9 8 9 4 10 0 8 5 8 3 2 1 4 5 9 4 7 9 3 9 10 1 9 9 10 5 3 3 10 4 2 2 5 0 9 7 2 5 5

No hay necesidad de apply . =)

EDITAR

También deberías echarle un vistazo al paquete norm . Tiene muchas características interesantes para el análisis de datos faltantes. =)


ejemplo dplyr

library(dplyr) df1 <- df1 %>% mutate(myCol1 = if_else(is.na(myCol1), 0, myCol1))

Nota: Esto funciona para cada columna seleccionada, si necesitamos hacer esto para todas las columnas, vea la respuesta de mutate_each usando mutate_each .