2016-12-07 94 views
2

我有以下data.table,其中每个唯一的x值与唯一的y值相关联。于是我强迫一个x价值NA第k近邻锻炼的目的:knnImpute使用分类变量与插入符号包

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?如果是这样,我需要在脚本中更改哪些内容?如果不是,为什么?

回答

3

要了解发生了什么事情,首先需要了解caret包的工作原理preProcess中的方法knnImpute的工作方式。各种风格的k-最近的邻居插补是可用的,不同的人在不同的软件包中以不同的方式实现它。

您可以使用加权平均数,中位数或甚至简单平均值来替换缺失值。有几个距离度量来计算找到邻居的不同距离。

现在具体到你的问题这里是一些问题,他们的答案出现了。

1.这里最近的邻居有多少?

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

2.正在使用哪个距离度量?

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

3.计算距离的距离和发现距离的尺寸是多少?

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

基于上述的解释,如果你尝试删除存储在preobj$dataNA行后,发现在数据集中的五个最近的邻居(nn),你会得到下面的指标(nn.idx)和相应的距离( 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.Now最后如何更换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

+0

很好的解释。对于我的具体情况,我在'preProcess'函数中做了'k = 2',它给了我期望看到的东西。然后,我重新创建了我的'dt'表,并在'preProcess'函数中重复了11次重复并使用'k = 10',并且现在仍然可以得到相同的答案。 – bshelt141