R найти ближайшего соседа для выбранной точки - PullRequest
1 голос
/ 02 марта 2020

У меня есть файл csv только с 20 точками данных, и я хотел бы знать ближайшего соседа для новой точки данных.

Мой CSV-файл выглядит следующим образом

temp    rain
79        12
81        13 
79        4
61        9
60        15
45        5
34        5
100       9
101       3
59        11
58        16

Поэтому я хотел бы знать, как правильно найти ближайшего соседа для точки 65, 7, используя евклидово расстояние и KNN. Большинство доступных в сети алгоритмов используют большие наборы данных, такие как iris или German от R, но они настолько малы, что не требуют очистки, поэтому мне кажется, что эти решения слишком усложняют эту проблему. Я все еще очень плохо знаком с R, так что, возможно, я упустил решение. Спасибо, что нашли время, чтобы прочитать это!

Я попробовал следующий код, но он продолжает выдавать ошибку, опять же, я думаю, я просто слишком усложняю это

df <- read.csv("data.csv", header = FALSE, sep = ',')

head(df) 

ran <- sample(1:nrow(df), 0.9 * nrow(df)) 

nor <-function(x) { (x -min(x))/(max(x)-min(x))   }

df_train <- df[ran,] 

df_test <- df[-ran,] 
##extract 5th column of train dataset because it will be used as 'cl' argument in knn function.
df_target_category <- df[ran,2]
##extract 5th column if test dataset to measure the accuracy
df_test_category <- df[-ran,2]

library(class)

pr <- knn(df_train,df_test,cl=df_target_category,k=13)

##create confusion matrix
tab <- table(pr,df_test_category)

accuracy <- function(x){sum(diag(x)/(sum(rowSums(x)))) * 100}
accuracy(tab)

Ответы [ 2 ]

1 голос
/ 03 марта 2020

Я думаю, что базы R достаточно для расчета евклидова расстояния, т. Е.

distance <- sqrt(rowSums((df-do.call(rbind,replicate(nrow(df),p,simplify = FALSE)))**2))
nearest <- df[which.min(distance),]

таким, что

> nearest
  temp rain
4   61    9

DATA

df <- structure(list(temp = c(79L, 81L, 79L, 61L, 60L, 45L, 34L, 100L, 
101L, 59L, 58L), rain = c(12L, 13L, 4L, 9L, 15L, 5L, 5L, 9L, 
3L, 11L, 16L)), class = "data.frame", row.names = c(NA, -11L))

p <- structure(list(temp = 65, rain = 7), class = "data.frame", row.names = c(NA, 
-1L))

1 голос
/ 03 марта 2020

Я не уверен, как ваш вопрос связан с KNN. Почему бы просто не вычислить евклидово расстояние новой точки до всех других точек в df, а затем определить, какая точка в df является ближайшей? Для этого мы можем использовать R * dist, который возвращает (по умолчанию: евклидово) матрицу расстояний.

Вот минимальный пример в два этапа, основанный на приведенном вами примере.

# Calculate Euclidean distances of `pt` to all points in `df`
dist_to_pt <- as.matrix(dist(rbind(df, pt)))[nrow(df) + 1, 1:nrow(df)]

# Determine the point in `df` with minimal distance to `pt`
dist_to_pt[which.min(dist_to_pt)]
#       4
#4.472136

Таким образом, точка 4 в df является ближайшим соседом к новой точке в (65, 7).

Мы можем визуализировать старые и новые данные

library(dplyr)
library(ggplot2)
rbind(df, pt) %>%
    mutate(
        pt_number = row_number(),
        source = ifelse(pt_number > nrow(df), "new", "ref")) %>%
    ggplot(aes(temp, rain, colour = source, label = pt_number)) +
    geom_point() +
    geom_text(position = position_nudge(y = -0.5))

enter image description here

Точка 4 является ближайшим соседом новой точки 12 в точке (65, 7).


Пример данных

df <- read.table(text =
    "temp    rain
79        12
81        13
79        4
61        9
60        15
45        5
34        5
100       9
101       3
59        11
58        16", header = T)

# New point
pt <- c(temp = 65, rain = 7)
...