【问题标题】:Randomly insert NAs into dataframe proportionaly随机按比例将名称插入数据帧
【发布时间】:2015-02-11 18:59:19
【问题描述】:

我有一个完整的数据框。我想将数据框中 20% 的值替换为 NA,以模拟随机缺失的数据。

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

任何人都可以提出一个快速的方法吗?

【问题讨论】:

  • 您的意思是每个变量的 15%?还是整体观察?
  • 20% 没问题(即 6 的值应该是 NA)
  • 您可能想查看这个答案,它可以为您提供准确的 NA 比例:stackoverflow.com/q/39513837/3871924

标签: r dataframe na missing-data


【解决方案1】:
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%。

【讨论】:

    【解决方案2】:

    您可以取消列出 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() 以多种不同的方式完成。

    【讨论】:

      【解决方案3】:

      同样的结果,使用二项分布:

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

      【讨论】:

        【解决方案4】:

        我可以建议第一个函数 (ggNAadd) 用于执行此操作,并使用提供创建的 NA 的图形分布 (ggNA) 的第二个函数来改进它

        简洁的是可以输入固定数量的 NA 的一部分。

        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
        ## ..
        

        当然,如前所述,如果你问太多 NA,实际百分比会因为重复而下降。

        【讨论】:

          【解决方案5】:

          如果你有心情使用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
          

          【讨论】:

            【解决方案6】:

            mutate_all 方法:

            df %>% 
              dplyr::mutate_all(~ifelse(sample(c(TRUE, FALSE), size = length(.), replace = TRUE, prob = c(0.8, 0.2)),
                     as.character(.), NA))
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2018-09-26
              • 1970-01-01
              • 2013-05-29
              • 1970-01-01
              • 2017-09-23
              • 2017-09-13
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多