插入符号 returns 中使用预处理的数据插补比预期少

Data imputation with preProcess in caret returns less observations than expected

我想知道为什么 preProcess 来自 R 的 caret 包的函数用于估算数据集的缺失值 returns 比原始数据集中的观测值少?
例如:

library(caret)

t <- data.frame(seq_len(100000),seq_len(100000))

for (i in 1:100000) 
{
if (i %% 10 == 0) t[i,1] <- NA; 
if (i %% 100 == 0) t[i,2] <- NA 
}

preProcValues <- preProcess(t, method = c("knnImpute"))

preProcValues 将仅包含 2 个变量的 90000 个观察值,而预期为 100000 个。

来自文档:

The function preProcess estimates the required parameters for each operation and predict.preProcess is used to apply them to specific data sets.

这里的preProcValues不是插补后的t,它包含了使用predict.preProcesst进行插补所需的参数。


您应该而不是期望在preProcValues

中有 100K 个观测值

提示:查看 source code 以了解 NA

的幕后情况

使用您的示例(修改为使用 method = "medianImpute" - 请参阅此 question(以及上述源代码)以了解您尝试执行的操作为何不适用于 "knnImpute")

preProcValues <- preProcess(t, method = "medianImpute") 
> preProcValues$dim[1]
#[1] 90000

这里我们将t中的NA值替换为中位数(50K)

t2 <- predict(preProcValues, t)
> dim(t2)[1]
#[1] 100000

preProcess 没有 return 值,它只是根据提供的数据建立整个预处理模型。所以,你需要 运行 predict (还需要 RANN 包),但即使你用你的人工数据这样做,你也会得到一个错误:

Error in FUN(newX[, i], ...) : cannot impute when all predictors are missing in the new data point

因为 k-nn 插补无法在 两个 你的预测变量都是 NA 的行中工作。

为了清晰和便于检查,这里有一个只有 20 行的演示:

library(caret)

t <- data.frame(seq_len(20),seq_len(20))

for (i in 1:20) 
{
  if (i %% 3 == 0) t[i,1] <- NA; 
  if (i %% 7 == 0) t[i,2] <- NA 
}

names(t) <- c('V1', 'V2')

preProcValues <- preProcess(t, method = c("knnImpute"))

library(RANN)

t_imp <- predict(preProcValues, t)

查看结果时,请记住方法 "center", "scale" 已自动添加到您的预处理中,即使您没有显式调用它们也是如此:

> str(preProcValues)
List of 19
$ call      : language preProcess.default(x = t, method = c("knnImpute"))
$ dim       : int [1:2] 12 2
$ bc        : NULL
$ yj        : NULL
$ et        : NULL
$ mean      : Named num [1:2] 10.5 10.5
 ..- attr(*, "names")= chr [1:2] "V1" "V2"
$ std       : Named num [1:2] 6.25 6.14
 ..- attr(*, "names")= chr [1:2] "V1" "V2"
$ ranges    : NULL
$ rotation  : NULL
$ method    : chr [1:3] "knnImpute" "scale" "center"
$ thresh    : num 0.95
$ pcaComp   : NULL
$ numComp   : NULL
$ ica       : NULL
$ k         : num 5
$ knnSummary:function (x, ...)  
$ bagImp    : NULL
$ median    : NULL
$ data      : num [1:12, 1:2] -1.434 -1.283 -0.981 -0.83 -0.377 ...
 ..- attr(*, "dimnames")=List of 2
 .. ..$ : chr [1:12] "1" "2" "4" "5" ...
 .. ..$ : chr [1:2] "V1" "V2"
 ..- attr(*, "scaled:center")= Named num [1:2] 10.5 10.5
 .. ..- attr(*, "names")= chr [1:2] "V1" "V2"
 ..- attr(*, "scaled:scale")= Named num [1:2] 6.63 6.63
 .. ..- attr(*, "names")= chr [1:2] "V1" "V2"
- attr(*, "class")= chr "preProcess"