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