2014-12-13 9 views
5

У меня есть полный dataframe. Я хочу, чтобы 20% значений в фрейме данных были заменены на НС, чтобы имитировать случайные отсутствующие данные.Случайно вставьте NAs в пропорциональную пропорцию данных

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

Может ли кто-нибудь предложить быстрый способ сделать это?

+0

Вы имеете в виду 15% от каждой переменной? или общие наблюдения? – Robert

+0

20% в порядке (то есть 6 значений должно быть NA) – Filly

+1

Возможно, вы захотите проверить этот ответ, который дает точные пропорции NA: https://stackoverflow.com/q/39513837/3871924 – agenis

ответ

6
df <- data.frame(A = 1:10, B = 11:20, c = 21:30) 
head(df) 
## A B 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) ])) 
##  A B 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 

Это случайный процесс, поэтому он может не давать 15% каждый раз.

4

Вы можете заблокировать data.frame, а затем взять произвольный образец, а затем вернуть обратно в data.frame.

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

С помощью sample() можно сделать кучу разных способов.

0

того же результат, используя биномиальное распределение:

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

Может ли я предложить первую функцию (ggNAadd) разработано, чтобы сделать это, и улучшить его с второй функцией обеспечения графического распределения САМОГО созданным (ggNA)

Что является опрятным, это возможность вводить либо долю фиксированного числа НС.

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

И функция зарисовки:

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

Что дает (с использованием ggplot2 в качестве графического вывода):

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

enter image description here

Конечно, как уже упоминалось ранее, если вы спросите слишком много NAs, фактический процент упадет из-за повторений.

3

Если вы в настроении, чтобы использовать purrr вместо lapply, вы также можете сделать это так:

> library(purrr) 
> df <- data.frame(A = 1:10, B = 11:20, C = 21:30) 
> df 
    A B 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 
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 
     A  B  C 
    <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 
Смежные вопросы