data.table的平均插补问题

时间:2017-05-31 13:33:47

标签: r data.table

尝试使用此循环在所有数字行中插入缺失值:

for(i in 1:ncol(df)){
  if (is.numeric(df[,i])){
    df[is.na(df[,i]), i] <- mean(df[,i], na.rm = TRUE)
  }
}

当没有附加data.table包时,上面的代码正常工作。一旦我附加了data.table包,那么行为就会改变,它会显示错误:

Error in `[.data.table`(df, , i) : 
  j (the 2nd argument inside [...]) is a single symbol but column name 'i' 
is not found. Perhaps you intended DT[,..i] or DT[,i,with=FALSE]. This 
difference to data.frame is deliberate and explained in FAQ 1.1.

我试过了......我在&#39;并且&#39; = = FALSE&#39;到处都没有成功。实际上它甚至没有通过第一个是.numeric条件。

2 个答案:

答案 0 :(得分:2)

在这种情况下,data.table语法略有不同。你可以这样做:

num_cols <- names(df)[sapply(df, is.numeric)]
for(col in num_cols) {
  set(df, i = which(is.na(df[[col]])), j = col, value = mean(df[[col]], na.rm=TRUE))
}

或者,如果您想继续使用现有循环,只需使用

将数据转回data.frame即可
setDF(df)

答案 1 :(得分:0)

这个问题的另一种答案是,我在大规模地遇到类似问题时想出了办法。可能有兴趣通过使用[.data.table方法来避免循环。

DF[i, j, by, on, ...]

首先,我们将创建一个可以执行插补的功能

 impute_na <- function(x, val = mean, ...){
   if(!is.numeric(x))return(x)
   na <- is.na(x)
   if(is.function(val))
     val <- val(x[!na])
   if(!is.numeric(val)||length(val)>1)
     stop("'val' needs to be either a function or a single numeric value!")
   x[na] <- val
   x
 }

要在数据帧上执行插补,可以在data.table环境中创建和评估一个表达式,但是为了示例简单起见,我们将使用<-

覆盖
DF <- DF[, lapply(.SD, impute_na)]

这将推算所有数字列的均值,并使所有非数字列保持不变。如果我们希望输入另一个值(例如... 42或其他值),并且也许我们有一些分组变量,那么我们只希望通过该变量就可以计算出均值即可

DF <- DF[, lapply(.SD, impute_na, val = 42)]
DF <- DF[, lapply(.SD, impute_NA), by = group]

分别估算42和组内均值。