Randomly insert NA into proportional proportion of data

I have a full frame. I want 20% of the values ​​in the data frame to be replaced by NS to simulate random missing data.

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

Can anyone suggest a quick way to do this?

+5
source share
5 answers
 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 

This is a random process, so it may not give 15% each time.

+6
source

You can lock the data.frame file and then take a random selection and then return it back to data.frame.

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

Using sample (), you can do several different ways.

+4
source

If you are configured to use purrr instead of lapply , you can also do it like this:

 > 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 <int> <int> <int> 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 
+3
source

Same result using binomial distribution:

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

Can I suggest the first function (ggNAadd) designed for this, and improve it with a second function that provides a graphical distribution of the generated NA (ggNA)

What is neat is the ability to enter either a fraction of a fixed number of NS.

 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) } 

And the plotting function:

 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) } 

What gives (using ggplot2 as graphical output):

 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

Of course, as mentioned earlier, if you ask too many NSs, the actual percentage will fall due to repetitions.

0
source

Source: https://habr.com/ru/post/1208927/


All Articles