Le calcul de toutes les distances entre un point et un groupe de points efficacement dans la R

Tout d'abord, je suis nouveau sur R (j'ai commencé hier).

J'ai deux groupes de points, data et centers, la première de taille n et le second, de taille K (par exemple, n = 3823 et K = 10), et pour chaque i dans le premier set, j'ai besoin de trouver j dans la seconde, avec le minimum de distance.

Mon idée est simple: pour chaque i, laissez dist[j] la distance entre i et j, j'ai seulement besoin d'utiliser which.min(dist) à trouver ce que je cherche.

Chaque point est un tableau de 64 doubles, de sorte

> dim(data)
[1] 3823   64
> dim(centers)
[1] 10 64

J'ai essayé avec

for (i in 1:n) {
  for (j in 1:K) {
    d[j] <- sqrt(sum((centers[j,] - data[i,])^2))
  }
  S[i] <- which.min(d)
}

qui est extrêmement lent (avec n = 200, il faut plus de 40 ans!!). La solution la plus rapide que j'ai écrit est

distance <- function(point, group) {
  return(dist(t(array(c(point, t(group)), dim=c(ncol(group), 1+nrow(group)))))[1:nrow(group)])
}

for (i in 1:n) {
  d <- distance(data[i,], centers)
  which.min(d)
}

Même si il fait beaucoup de calcul que je ne l'utilise pas (parce que dist(m) calcule la distance entre toutes les lignes de m), c'est plus rapide que l'autre (quelqu'un peut-il expliquer pourquoi?), mais il n'est pas assez rapide pour ce dont j'ai besoin, car il ne peut être utilisé qu'une seule fois. Et aussi, le distance code est très laid. J'ai essayé de le remplacer par

distance <- function(point, group) {
  return (dist(rbind(point,group))[1:nrow(group)])
}

mais ce qui semble être deux fois plus lentement. J'ai aussi essayé d'utiliser dist pour chaque paire, mais il est aussi plus lent.

Je ne sais pas quoi faire maintenant. Il me semble que je suis en train de faire quelque chose de très mal. Aucune idée sur comment faire cela de manière plus efficace?

ps: j'en ai besoin pour mettre en œuvre des k-means à la main (et j'ai besoin de le faire, c'est le cadre d'une cession). Je crois que je vais seulement besoin de distance Euclidienne, mais je ne suis pas encore certain, donc je préfère avoir un peu de code où la distance de calcul peut être remplacé facilement. stats::kmeans faire tout le calcul en moins d'une seconde.

Les gens ici genre-une-ne-ressemble-à faire des travaux... donc essayez de vous concentrer sur un problème spécifique.

OriginalL'auteur dbarbosa | 2010-06-12