Supposons que j'ai deux ensembles de données. Le premier est:
sumPD<-function(vector1,vector2){ sumPD1<-sum((vector1-vector2)^2) return(sumPD1) } loc<-matrix(NA,nrow=dim(xtrain)[1],ncol=dim(xtest)[1]) for(j in 1:dim(xtest)[1]){ for(i in 1:dim(xtrain)[1]){ loc[i,j]<-sumPD(xtrain[i,],xtest[j,]) } }
Le second est:
sum((7-1)^2+(3-5)^2+(9-8)^2+.....(9-5)^2) sum((5-1)^2+(1-5)^2+(1-8)^2+.....(4-5)^2) ... sum((14-13)^2+(18-14)^2+(15-18)^2+.....(17-14)^2)
Ce que j'ai aimé faire, c'est calculer la somme de la distance entre chaque ligne de xtest
et chaque ligne de xtrain
. Par exemple:
t6<-sample(1:10,10,replace = T) t7<-sample(11:20,10,replace = T) xtest<-rbind(t6,t7) xtest [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] t6 1 5 8 2 10 2 3 4 8 5 t7 14 18 15 12 17 20 17 13 16 17
Ce que j'ai actuellement, c'est d'utiliser deux boucles for (voir ci-dessous), qui, je pense, ne peuvent pas gérer de grands ensembles de données:
t1<-sample(1:10,10,replace = T) t2<-sample(1:10,10,replace = T) t3<-sample(1:10,10,replace = T) t4<-sample(11:20,10,replace = T) t5<-sample(11:20,10,replace = T) xtrain<-rbind(t1,t2,t3,t4,t5) xtrain [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] t1 7 3 9 10 4 9 2 1 6 9 t2 5 1 1 6 5 3 10 2 6 3 t3 8 6 9 7 9 2 3 5 1 8 t4 16 18 14 17 19 20 15 15 20 19 t5 13 14 18 13 11 19 13 17 16 14
Je voudrais demander des suggestions sur la façon de modifier le code pour le rendre efficace. Merci d'avance! J'espère avoir une bonne discussion!
4 Réponses :
Une option serait outer
f1 <- Vectorize(function(i, j) sumPD(xtrain[i,], xtest[j,])) loc2 <- outer(seq_len(nrow(xtrain)), seq_len(nrow(xtest)), f1) identical(loc, loc2) #[1] TRUE
Le package rdist
a des fonctions pour calculer rapidement ces types de distances par paires:
[,1] [,2] [1,] 65 1029 [2,] 94 1324 [3,] 165 1103 [4,] 1189 213 [5,] 1271 191
Sortie:
rdist::cdist(xtrain, xtest)^2
Voici deux méthodes simples.
En utilisant dist
- calculera plus de distances que nécessaire:
euclid <- function(X,y) colSums((X-y)^2) dists <- mapply(euclid, list(t(xtrain)), split(xtest, row(xtest))) dists [,1] [,2] t1 140 1179 t2 134 693 t3 119 974 t4 1028 91 t5 1085 44
En utilisant des fonctions personnalisées simples qui fonctionne sur la matrice X et le vecteur y:
dists <- as.matrix(dist(rbind(xtrain, xtest))^2) dists <- dists[rownames(xtrain), rownames(xtest)] dists t6 t7 t1 140 1179 t2 134 693 t3 119 974 t4 1028 91 t5 1085 44
Vous pouvez transposer votre matrice, utiliser la différence vectorielle et une seule boucle:
ftrain <- t(xtrain) ftest <- t(xtest) sapply(1:(dim(ftest)[2]),function(i){ colSums((ftrain - ftest[,i])^2) }) [,1] [,2] t1 103 1182 t2 125 1262 t3 130 1121 t4 1478 159 t5 1329 142
colSums
est assez efficace, mais regardez là si vous voulez plus de vitesse
Je pense que vous pouvez éviter la boucle avec ntrain = nrow (xtrain); ntest = nrow (xtest); matrix (rowSums ((xtrain [rep (1: ntrain, ntest),] - xtest [rep (1: ntest, each = ntrain),]) ^ 2), nc = ntest)
bien que l'intention est plus clair