Inserte aleatoriamente las NA en la proporcionalidad del dataframe

Tengo un dataframe completo. Quiero que el 20% de los valores en el dataframe sean reemplazados por NA para simular datos faltantes aleatorios.

A <- c(1:10) B <- c(11:20) C <- c(21:30) df<- data.frame(A,B,C) 

¿Alguien puede sugerir una manera rápida de hacer eso?

 df < - data.frame(A = 1:10, B = 11:20, c = 21:30) head(df) ## AB c ## 1 1 11 21 ## 2 2 12 22 ## 3 3 13 23 ## 4 4 14 24 ## 5 5 15 25 ## 6 6 16 26 as.data.frame(lapply(df, function(cc) cc[ sample(c(TRUE, NA), prob = c(0.85, 0.15), size = length(cc), replace = TRUE) ])) ## AB c ## 1 1 11 21 ## 2 2 12 22 ## 3 3 13 23 ## 4 4 14 24 ## 5 5 NA 25 ## 6 6 16 26 ## 7 NA 17 27 ## 8 8 18 28 ## 9 9 19 29 ## 10 10 20 30 

Es un proceso aleatorio, por lo que podría no dar el 15% cada vez.

Puede deslistar el data.frame y luego tomar una muestra aleatoria, luego volver a colocarla en un data.frame.

 df < - unlist(df) n <- length(df) * 0.15 df[sample(df, n)] <- NA as.data.frame(matrix(df, ncol=3)) 

Se puede hacer de varias maneras usando sample ().

Si está de humor para usar purrr lugar de lapply , también puede hacerlo así:

 > library(purrr) > df < - data.frame(A = 1:10, B = 11:20, C = 21:30) > df ABC 1 1 11 21 2 2 12 22 3 3 13 23 4 4 14 24 5 5 15 25 6 6 16 26 7 7 17 27 8 8 18 28 9 9 19 29 10 10 20 30 > map_df(df, function(x) {x[sample(c(TRUE, NA), prob = c(0.8, 0.2), size = length(x), replace = TRUE)]}) # A tibble: 10 x 3 ABC    1 1 11 21 2 2 12 22 3 NA 13 NA 4 4 14 NA 5 5 15 25 6 6 16 26 7 7 17 27 8 8 NA 28 9 9 19 29 10 10 20 30 

Mismo resultado, usando distribución binomial:

 dd=dim(df) nna=20/100 #overall df1< -df df1[matrix(rbinom(prod(dd), size=1,prob=nna)==1,nrow=dd[1])]<-NA df1 

¿Puedo sugerir una primera función (ggNAadd) diseñada para hacer esto y mejorarla con una segunda función que proporcione una distribución gráfica de las NA creadas (ggNA)?

Lo que está claro es la posibilidad de ingresar una proporción de un número fijo de AN.

 ggNAadd = function(data, amount, plot=F){ temp < - data amount2 <- ifelse(amount<1, round(prod(dim(data))*amount), amount) if (amount2 >= prod(dim(data))) stop("exceeded data size") for (i in 1:amount2) temp[sample.int(nrow(temp), 1), sample.int(ncol(temp), 1)] < - NA if (plot) print(ggNA(temp)) return(temp) } 

Y la función de trazado:

 ggNA = function(data, alpha=0.5){ require(ggplot2) DF < - data if (!is.matrix(data)) DF <- as.matrix(DF) to.plot <- cbind.data.frame('y'=rep(1:nrow(DF), each=ncol(DF)), 'x'=as.logical(t(is.na(DF)))*rep(1:ncol(DF), nrow(DF))) size <- 20 / log( prod(dim(DF)) ) # size of point depend on size of table g <- ggplot(data=to.plot) + aes(x,y) + geom_point(size=size, color="red", alpha=alpha) + scale_y_reverse() + xlim(1,ncol(DF)) + ggtitle("location of NAs in the data frame") + xlab("columns") + ylab("lines") pc <- round(sum(is.na(DF))/prod(dim(DF))*100, 2) # % NA print(paste("percentage of NA data: ", pc)) return(g) } 

Que da (usando ggplot2 como salida gráfica):

 ggNAadd(df, amount=0.20, plot=TRUE) ## [1] "percentage of NA data: 20" ## AB c ## 1 1 11 21 ## 2 2 12 22 ## 3 3 13 23 ## 4 4 NA 24 ## .. 

enter image description here

Por supuesto, como se mencionó anteriormente, si pide demasiadas NA, el porcentaje real disminuirá debido a las repeticiones.