删除所有缺失值超过 30% 的变量

Deleting all variables with over 30% missing values

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

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 循环,它会去掉 more 直到 3 或 4 次,直到它去掉所有的变量。为什么会这样?请随时纠正我的问题,或者想出一个更好的方法来删除 NAs 超过 30% 的变量。

你可以这样使用:

df <- df[colSums(is.na(df))/nrow(df) < .3]
  • colSums(is.na(df)) 将计算每列中有多少个 NA 值。
  • 将该输出除以 data.frame 中的行数以获得比例。
  • 使用 < .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 

我们可以使用 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 的 post