【问题标题】:Deleting all variables with over 30% missing values删除所有缺失值超过 30% 的变量
【发布时间】:2016-04-06 18:16:49
【问题描述】:

我发现这个函数可以检测任何给定数据帧中每一列的缺失值比例:

propmiss <- function(dataframe) lapply(dataframe,function(x) data.frame(nmiss=sum(is.na(x)), n=length(x), propmiss=sum(is.na(x))/length(x)))

我将它分配给这样的变量:

propmissdf <- propmiss(df)  

然后我循环遍历数据框到我的数据中的 NULL 变量,如下所示:

for(i in (1:length(df))){  
  var = names(df)[i]
  if((propmissdf[[var]][[3]]) > 0.3) { #the 3 index represents the proportion inside propmissdf
  df[var] <- NULL   
   }
}

这给了我一个错误:

Error in if ((propmissdf[[var]][[3]]) > 0.3) { :argument is of length zero

但它工作,不知何故。它消除了几个缺失值比例大于 0.3 的变量,但如果我再次运行 for 循环,它会消除更多的变量,直到 3 或 4 次以上,直到消除所有变量。为什么会这样?请随时纠正我的问题,或提出更好的方法来删除 NA 超过 30% 的变量。

【问题讨论】:

    标签: r missing-data


    【解决方案1】:

    你可以这样使用:

    df <- df[colSums(is.na(df))/nrow(df) < .3]
    
    • colSums(is.na(df)) 将计算每列中有多少 NA 值。
    • 将该输出除以data.frame 中的行数以获得比例。
    • 使用&lt; .3 创建可用于对相关列进行子集化的逻辑比较。

    示例数据和示例:

    set.seed(2)
    df <- data.frame(matrix(sample(c(NA, 1:4), 20, TRUE), nrow = 4))
    df
    #   X1 X2 X3 X4 X5
    # 1 NA  4  2  3  4
    # 2  3  4  2 NA  1
    # 3  2 NA  2  2  2
    # 4 NA  4  1  4 NA
    
    colSums(is.na(df))/nrow(df)
    #   X1   X2   X3   X4   X5 
    # 0.50 0.25 0.00 0.25 0.25 
    
    df[colSums(is.na(df))/nrow(df) < .3]
    #   X2 X3 X4 X5
    # 1  4  2  3  4
    # 2  4  2 NA  1
    # 3 NA  2  2  2
    # 4  4  1  4 NA
    

    作为参考,这里有一个快速的时间比较:

    set.seed(1)
    df <- data.frame(matrix(sample(c(NA, 1:4), 4000, TRUE), ncol = 1000))
    
    akfun <- function() {
      i1 <-sapply(df, function(x) {
        pr <- prop.table(table(factor(is.na(x), levels=c(TRUE, FALSE))))
        pr[as.logical(names(pr))]< 0.3
      })
      df[i1]
    }
    
    amfun <- function() df[colSums(is.na(df))/nrow(df) < .3]
    
    identical(amfun(), akfun())
    # [1] TRUE
    
    system.time(akfun())
    #    user  system elapsed 
    #   0.172   0.000   0.173 
    system.time(amfun())
    #    user  system elapsed 
    #   0.000   0.000   0.001 
    

    【讨论】:

    • 在此之后您将如何将超过 0.3 的变量归零?
    • @jgozal,您只需重新分配输出:df &lt;- df[colSums(is.na(df))/nrow(df) &lt; .3]
    【解决方案2】:

    我们可以用sapply遍历列,用table获取'NA'值的count,使用`prop.table找到比例并创建一个逻辑向量。

    i1 <-sapply(df, function(x) {
    
          pr <- prop.table(table(factor(is.na(x), levels=c(TRUE, FALSE))))
    
          pr[as.logical(names(pr))]< 0.3
    
     })
    

    此向量可用于对列进行子集化。

    df[i1]
    

    如果我们需要删除列

    df[!i1] <- list(NULL) #contributed by @Ananda Mahto
    df
    #   X2 X3 X4 X5
    #1  4  2  3  4
    #2  4  2 NA  1
    #3 NA  2  2  2
    #4  4  1  4 NA
    

    注意:df 取自 @Ananda Mahto 的帖子

    【讨论】:

    • 试试df &lt;- cbind(df, df)。见here
    猜你喜欢
    • 1970-01-01
    • 2018-08-24
    • 2019-03-04
    • 1970-01-01
    • 1970-01-01
    • 2015-10-29
    • 2017-07-15
    • 1970-01-01
    • 2018-03-07
    相关资源
    最近更新 更多