【问题标题】:knnImpute using categorical variables with caret packageknnImpute 使用带有 caret 包的分类变量
【发布时间】:2016-12-16 16:32:24
【问题描述】:

我有以下 data.table,其中每个唯一的 x 值都与唯一的 y 值相关联。然后我将一个x 值强制为NA,用于k-最近邻练习:

dt <- data.table(x = rep(c(1:4), 3), 
                 y = rep(c("Brandon", "Erica", "Karyna", "Alex"), 3))
dt[3, 1] <- NA

print(dt)
 #    x       y
 #1:  1 Brandon
 #2:  2   Erica
 #3: NA  Karyna
 #4:  4    Alex
 #5:  1 Brandon
 #6:  2   Erica
 #7:  3  Karyna
 #8:  4    Alex
 #9:  1 Brandon
#10:  2   Erica
#11:  3  Karyna
#12:  4    Alex

参考this question 的第一个答案,我从dt$y 创建了一个二进制矩阵,如下所示:

dt.a <- model.matrix(~ y -1 , data = dt)
dt2 <- cbind(dt[, -2, with = FALSE], dt.a)

print(dt2)
 #    x yAlex yBrandon yErica yKaryna
 #1:  1     0        1      0       0
 #2:  2     0        0      1       0
 #3: NA     0        0      0       1
 #4:  4     1        0      0       0
 #5:  1     0        1      0       0
 #6:  2     0        0      1       0
 #7:  3     0        0      0       1
 #8:  4     1        0      0       0
 #9:  1     0        1      0       0
#10:  2     0        0      1       0
#11:  3     0        0      0       1
#12:  4     1        0      0       0

使用caret 包的preProcess 函数中的knnImpute 方法,我希望dt3[1, 3] 下面的中心和缩放输出将等于第7 行和第12 行。但事实并非如此。事实上,它看起来几乎等于第 7 行和第 12 行的负值。

preobj <- preProcess(dt2, method = "knnImpute")
dt3 <- predict(preobj, dt2)

print(dt3)
 #             x      yAlex   yBrandon     yErica    yKaryna
 #1: -1.19857753 -0.5527708  1.6583124 -0.5527708 -0.5527708
 #2: -0.37455548 -0.5527708 -0.5527708  1.6583124 -0.5527708
 #3: -0.04494666 -0.5527708 -0.5527708 -0.5527708  1.6583124
 #4:  1.27348863  1.6583124 -0.5527708 -0.5527708 -0.5527708
 #5: -1.19857753 -0.5527708  1.6583124 -0.5527708 -0.5527708
 #6: -0.37455548 -0.5527708 -0.5527708  1.6583124 -0.5527708
 #7:  0.44946657 -0.5527708 -0.5527708 -0.5527708  1.6583124
 #8:  1.27348863  1.6583124 -0.5527708 -0.5527708 -0.5527708
 #9: -1.19857753 -0.5527708  1.6583124 -0.5527708 -0.5527708
#10: -0.37455548 -0.5527708 -0.5527708  1.6583124 -0.5527708
#11:  0.44946657 -0.5527708 -0.5527708 -0.5527708  1.6583124
#12:  1.27348863  1.6583124 -0.5527708 -0.5527708 -0.5527708

dt3$x 的第 3 行不应该等于第 7 行和第 11 行吗?如果是这样,我需要在脚本中进行哪些更改?如果不是,为什么?

【问题讨论】:

    标签: r r-caret knn


    【解决方案1】:

    要了解发生了什么,您首先需要了解caret 包的函数preProcess 中的方法knnImpute 的工作方式。 k-nearest Neighbor imputation 有各种风格,不同的人在不同的软件包中以不同的方式实现它。

    您可以使用 k 最近邻的加权平均值、中值甚至简单平均值来替换缺失值。有几个距离度量来计算寻找邻居的不同距离。

    现在针对您的问题,这里有一些随着他们的回答而出现的问题。

    1.这里考虑了多少最近的邻居?

    默认为 5。您可以通过在preProcess函数中指定参数k来更改它。

    2.使用哪种距离度量?

    在上述情况下使用欧几里得距离。

    3.计算距离的空间维度是多少?如何求得?

    在您的情况下,它是四维空间。它是通过获取没有缺失值的列来获得的。因此,在您的情况下,它是列号 2, 3, 4, 5

    根据上述解释,如果您在删除存储在preobj$data 中的具有NA 的行后尝试在数据集中找到五个最近邻(nn),您将获得以下索引(@987654330 @ )和对应的距离(nn.dists)如下。

    > nn
    $nn.idx
         [,1] [,2] [,3] [,4] [,5]
    [1,]   10    6    5    9    2
    
    $nn.dists
         [,1] [,2]     [,3]     [,4]     [,5]
    [1,]    0    0 3.126944 3.126944 3.126944
    

    4.现在最后如何替换NA的值?

    要替换 NA 值,只需取缺失列中与最近索引对应的值的平均值。

    > preobj$data
                 x      yAlex   yBrandon     yErica    yKaryna
     1: -1.1985775 -0.5527708  1.6583124 -0.5527708 -0.5527708
     2: -0.3745555 -0.5527708 -0.5527708  1.6583124 -0.5527708
     3:  1.2734886  1.6583124 -0.5527708 -0.5527708 -0.5527708
     4: -1.1985775 -0.5527708  1.6583124 -0.5527708 -0.5527708
     5: -0.3745555 -0.5527708 -0.5527708  1.6583124 -0.5527708
     6:  0.4494666 -0.5527708 -0.5527708 -0.5527708  1.6583124
     7:  1.2734886  1.6583124 -0.5527708 -0.5527708 -0.5527708
     8: -1.1985775 -0.5527708  1.6583124 -0.5527708 -0.5527708
     9: -0.3745555 -0.5527708 -0.5527708  1.6583124 -0.5527708
    10:  0.4494666 -0.5527708 -0.5527708 -0.5527708  1.6583124
    11:  1.2734886  1.6583124 -0.5527708 -0.5527708 -0.5527708
    
    > mean(preobj$data$x[nn$nn.idx])
    [1] -0.04494666
    

    你会发现NA确实被输出中的这个值替换了。

    > dt3
                  x      yAlex   yBrandon     yErica    yKaryna
     1: -1.19857753 -0.5527708  1.6583124 -0.5527708 -0.5527708
     2: -0.37455548 -0.5527708 -0.5527708  1.6583124 -0.5527708
     3: -0.04494666 -0.5527708 -0.5527708 -0.5527708  1.6583124
     4:  1.27348863  1.6583124 -0.5527708 -0.5527708 -0.5527708
     5: -1.19857753 -0.5527708  1.6583124 -0.5527708 -0.5527708
     6: -0.37455548 -0.5527708 -0.5527708  1.6583124 -0.5527708
     7:  0.44946657 -0.5527708 -0.5527708 -0.5527708  1.6583124
     8:  1.27348863  1.6583124 -0.5527708 -0.5527708 -0.5527708
     9: -1.19857753 -0.5527708  1.6583124 -0.5527708 -0.5527708
    10: -0.37455548 -0.5527708 -0.5527708  1.6583124 -0.5527708
    11:  0.44946657 -0.5527708 -0.5527708 -0.5527708  1.6583124
    12:  1.27348863  1.6583124 -0.5527708 -0.5527708 -0.5527708
    

    注意第三行。

    要将NA 的值简单地替换为最近邻居的对应值,您可以简单地使用k=1

    【讨论】:

    • 很好的解释。对于我的具体情况,我在preProcess 函数中创建了k = 2,它给了我预期的结果。然后我重新创建了我的 dt 表并重复了 11 次 rep 函数,并在 preProcess 函数中使用了 k = 10 并且现在仍然能够得到相同的答案。
    猜你喜欢
    • 1970-01-01
    • 2014-02-10
    • 2013-12-18
    • 2016-09-29
    • 2018-02-13
    • 2020-10-14
    • 2018-08-12
    • 2015-08-29
    • 2018-05-14
    相关资源
    最近更新 更多