knnImpute с использованием категориальных переменных с пакетом каретки

У меня есть следующая таблица данных, где каждое уникальное значение 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

Ссылаясь на первый ответ на этот вопрос, Я создал двоичную матрицу из 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

Используя метод knnImpute из функции preProcess пакета caret, я ожидал бы, что вывод с масштабированием по центру ниже 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

Разве строка 3 dt3$x не должна равняться строкам 7 и 11? Если да, что мне нужно изменить в моем сценарии? Если нет, то почему?


person bshelt141    schedule 07.12.2016    source источник


Ответы (1)


Чтобы понять, что происходит, вам сначала нужно понять, как работает метод knnImpute в функции preProcess пакета caret. Доступны различные варианты вменения k-ближайшего соседа, и разные люди реализуют его по-разному в разных программных пакетах.

вы можете использовать средневзвешенное, медианное или даже простое среднее значение k-ближайшего соседа для замены отсутствующих значений. Есть несколько метрик расстояния для расчета различных расстояний для поиска соседей.

Теперь конкретно для ваших проблем вот несколько вопросов, которые возникают с их ответом.

1.Сколько здесь учитывается ближайших соседей?

По умолчанию 5. Вы можете изменить его, указав параметр k в функции preProcess.

2.Какой показатель расстояния используется?

В приведенном выше случае используется евклидово расстояние.

3. Каков размер пространства, в котором рассчитывается расстояние, и как оно определяется?

В вашем случае это четырехмерное пространство. Он получается путем выбора столбцов, в которых отсутствуют пропущенные значения. Следовательно, в вашем случае это номер столбца 2, 3, 4, 5.

Основываясь на приведенном выше объяснении, если вы попытаетесь найти пять ближайших соседей (nn) в наборе данных после удаления строки с NA, которая хранится в preobj$data, вы получите следующие индексы (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.Как, наконец, заменить значение 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.

person 9Heads    schedule 16.12.2016
comment
отличное объяснение. Для моего конкретного сценария я сделал k = 2 в функции preProcess, и это дало мне то, что я ожидал увидеть. Затем я воссоздал свою dt таблицу и сделал rep функции с 11 повторениями и использовал k = 10 в функции preProcess, и теперь смог получить тот же ответ. - person bshelt141; 16.12.2016