Я пытаюсь вычислить расстояние Махаланобиса между каждым наблюдением набора данных dat
, где каждая строка является наблюдением, а каждый столбец является переменной. Такое расстояние определяется как:Расстояние Махаланобиса каждой пары наблюдений
Я написал функцию, которая делает это, но я чувствую, что это очень медленный процесс. Есть ли лучший способ вычислить это в R?
Для создания некоторых данных для тестирования функции:
generateData <- function(nObs, nVar){
library(MASS)
mvrnorm(n=nObs, rep(0,nVar), diag(nVar))
}
Это функция, которую я написал до сих пор. Они работают и для моих данных (800 общ и 90 переменных), для method = "forLoop"
и method = "apply"
требуется приблизительно 30 и 33 секунды соответственно.
mhbd_calc2 <- function(dat, method) { #Method is either "forLoop" or "apply"
dat <- as.matrix(na.omit(dat))
nObs <- nrow(dat)
mhbd <- matrix(nrow=nObs,ncol = nObs)
cv_mat_inv = solve(var(dat))
distMH = function(x){ #Mahalanobis distance function
diff = dat[x[1],]-dat[x[2],]
diff %*% cv_mat_inv %*% diff
}
if(method=="forLoop")
{
for (i in 1:nObs){
for(j in 1:i){
mhbd[i,j] <- distMH(c(i,j))
}
}
}
if(method=="apply")
{
mhbd[lower.tri(mhbd)] = apply(combn(nrow(dat),2),2, distMH)
}
result = sqrt(mhbd)
colnames(result)=rownames(dat)
rownames(result)=rownames(dat)
return(as.dist(result))
}
NB: Я попытался с помощью outer()
, но это было еще медленнее (60seconds)
Итак, если я правильно понимаю, вы dist.maha немного менее точны, но гораздо быстрее? С точностью 7 цифр, это то же самое с моими испытаниями – Oligg
Возможно, я ошибаюсь, но метод choleski не проверяет, является ли матрица почти единственной. Если это так, это может дать большие значения, которые мы не хотим, нет? В то время как solve() выполняет эту проверку и возвращает ошибку, чтобы предотвратить ее. – Oligg
Я думаю, что это выходит за рамки моих знаний, но я обязательно спрошу. Кроме того, не могли бы вы немного рассказать о том, как работает ваш метод, если вы не возражаете? Эта функция сэкономит мне много времени, спасибо большое :) – Oligg