#r #matrix
#r #матрица
Вопрос:
Я пытаюсь закодировать функцию, которая определит, какая строка матрицы nxm M ближе всего к вектору y длины m.
Пожалуйста, что я делаю не так в своем коде? Я стремлюсь к тому, чтобы функция создавала вектор-столбец длиной n, который дает расстояние между координатами каждой строки матрицы и вектором y. Затем я хочу вывести номер строки матрицы, для которой это ближайшая точка к вектору.
closest.point <- function(M, y) {
p <- length(y)
k <- nrow(M)
T <- matrix(nrow=k)
T <- for(i in 1:n)
for(j in 1:m) {
(X[i,j] - x[j])^2 (X[i,j] - x[j])^2
}
W <- rowSums(T)
max(W)
df[which.max(W),]
}
Ответ №1:
Несмотря на то, что уже существует лучший подход (не использующий циклы for при работе с матрицами) к проблеме, я хотел бы предложить вам решение вашего подхода с помощью цикла for .
В вашей функции были некоторые ошибки. Существуют некоторые неопределенные переменные, такие как n, m или X.
Также старайтесь избегать именования переменных как T, поскольку R интерпретирует T как TRUE . Это работает, но может привести к некоторым ошибкам, если использовать T как TRUE в следующих строках кода.
При циклическом выполнении вам нужно указать индекс вашей переменной, которую вы обновляете, например T.matrix[i, j], а не только T.matrix, поскольку это перезапишет T.matrix на каждой итерации.
closest.point <- function(M, y) {
k <- nrow(M)
m <- ncol(M)
T.matrix <- matrix(nrow = k, ncol = m)
for (i in 1:k) {
for (j in 1:m) {
T.matrix[i, j] <- (M[i,j] - y[j])^2 (M[i,j] - y[j])^2
}
}
W <- rowSums(T.matrix)
return(which.min(W))
}
# example 1
closest.point(M = rbind(c(1, 1, 1),
c(1, 2, 5)),
y = cbind(c(1, 2, 5)))
# [1] 2
# example 2
closest.point(M = rbind(c(1, 1, 1, 1),
c(1, 2, 5, 7)),
y = cbind(c(2, 2, 6, 2)))
# [1] 2
Комментарии:
1. спасибо, я согласен, что другое решение более точное, но это действительно помогает мне понять, почему мое решение не работало с неопределенными переменными и т. Д.
Ответ №2:
Вы должны стараться избегать использования for
цикла для выполнения операций с векторами и матрицами. dist
Базовая функция вычисляет расстояния. Затем which.min
вы получите индекс минимального расстояния.
set.seed(0)
M <- matrix(rnorm(100), ncol = 5)
y <- rnorm(5)
closest_point <- function(M, y) {
dist_mat <- as.matrix(dist(rbind(M, y)))
all_distances <- dist_mat[1:nrow(M),ncol(dist_mat)]
which.min(all_distances)
}
closest_point(M, y)
#>
#> 14
Создано 2021-12-10 пакетом reprex (v2.0.1)
Надеюсь, это имеет смысл, дайте мне знать, если у вас есть вопросы.
Комментарии:
1. это намного аккуратнее — большое спасибо.
Ответ №3:
Здесь есть ряд проблем
- p определено, но никогда не используется.
- Хотя это и не так, T на самом деле не обязательно должно быть матрицей. Было бы достаточно, чтобы это был вектор.
- Хотя это и не неправильно, использование T в качестве переменной опасно, потому что T также означает TRUE .
- Код определяет T, и они немедленно отбрасывают его в следующем операторе, перезаписывая его. Предыдущий оператор, определяющий T, никогда не используется.
- for всегда имеет значение NULL, поэтому присваивать его T бессмысленно.
- цикл double for ничего не делает. В нем нет назначений, поэтому циклы не имеют никакого эффекта.
- циклы относятся к m, n, X и x, но они нигде не определены.
- (X[i,j] — x[j]) ^ 2 повторяется. Это необходимо только один раз.
- Запись max(W) в строке сама по себе не имеет никакого эффекта. Это приводит к выполнению печати только в том случае, если она выполняется непосредственно в консоли. Если выполняется в функции, это не имеет никакого эффекта. Если вы хотели ее распечатать, тогда напишите print(max(W)) .
- Нам нужна ближайшая точка, а не самая дальняя точка, поэтому max должно быть минимальным.
- df используется в последней строке, но нигде не определен.
- Вопрос является неполным без тестового запуска.
Я попытался внести минимальные изменения, чтобы это сработало:
closest.point <- function(M, y) {
nr <- nrow(M)
nc <- ncol(M)
W <- numeric(nr) # vector having nr zeros
for(i in 1:nr) {
for(j in 1:nc) {
W[i] <- W[i] (M[i,j] - y[j])^2
}
}
print(W)
print(min(W))
M[which.min(W),]
}
set.seed(123)
M <- matrix(rnorm(12), 4); M
## [,1] [,2] [,3]
## [1,] -0.56047565 0.1292877 -0.6868529
## [2,] -0.23017749 1.7150650 -0.4456620
## [3,] 1.55870831 0.4609162 1.2240818
## [4,] 0.07050839 -1.2650612 0.3598138
y <- rnorm(3); y
## [1] 0.4007715 0.1106827 -0.5558411
closest.point(M, y)
## [1] 0.9415062 2.9842785 4.6316069 2.8401691 <--- W
## [1] 0.9415062 <--- min(W)
## [1] -0.5604756 0.1292877 -0.6868529 <-- closest row
При этом вычисление ближайшей строки может быть выполнено в этой функции с однострочным телом. Мы транспонируем M, а затем вычитаем из него y, что приведет к вычитанию y из каждого столбца, но столбцы транспонирования являются строками M, поэтому это вычитает y из каждой строки. Затем возьмите суммы столбцов квадратов разностей и найдите, какой из них наименьший. Нижний индекс M использует это.
closest.point2 <- function(M, y) {
M[which.min(colSums((t(M) - y)^2)), ]
}
closest.point2(M, y)
## [1] -0.5604756 0.1292877 -0.6868529 <-- closest row
Комментарии:
1. спасибо — список проблем действительно полезен.