2014-12-13 10 views
5

Ich habe einen vollständigen Datenrahmen. Ich möchte 20% der Werte im Datenrahmen durch NAs ersetzen, um zufällig fehlende Daten zu simulieren.Zufällig einfügen NAs in Datenrahmen proportional

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

Kann jemand einen schnellen Weg vorschlagen?

+0

Sie meinen 15% der einzelnen Variablen? oder Gesamtbeobachtungen? – Robert

+0

20% ist in Ordnung (d. H. 6 des Werts sollte NA sein) – Filly

+1

Sie können diese Antwort, die Ihnen genaue Anteile von NA gibt, überprüfen: https://stackoverflow.com/q/39513837/3871924 – agenis

Antwort

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 

Es ist ein zufälliger Prozess, so dass es nicht immer 15% geben kann.

4

Sie können den data.frame aufheben und dann eine zufällige Stichprobe nehmen und dann in einen data.frame zurücklegen.

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

Es kann eine Reihe von verschiedenen Möglichkeiten mit sample() getan werden.

0

gleiches Ergebnis mit Binomialverteilung:

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

Darf ich vorschlagen, eine erste Funktion (ggNAadd) ausgelegt, dies zu tun, und verbessert sie mit einer zweiten Funktion grafische Verteilung der NAs erstellt (ggNA) Bereitstellen

Was ist sauber ist die Möglichkeit, entweder einen Anteil einer festen Anzahl von NAs einzugeben.

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

Und das Plotten Funktion:

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

Welche (mit ggplot2 als grafische Ausgabe) ergibt:

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

Natürlich, wie bereits erwähnt, Sie, wenn zu viele NAs fragen, wird der tatsächliche Prozentsatz wegen Wiederholungen fallen.

3

Wenn Sie in der Stimmung sind purrr statt lapply zu verwenden, können Sie auch tun es wie folgt aus:

> 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 
Verwandte Themen