Existe-t-il une fonction R qui calculera la matrice de dissimilarité cosinus? [fermé]


20

Je voudrais faire une carte thermique avec un regroupement de lignes basé sur les distances cosinus. J'utilise R et heatmap.2()pour faire la figure. Je peux voir qu'il y a un distparamètre heatmap.2mais je ne trouve pas de fonction pour générer la matrice de dissimilarité cosinus. La distfonction intégrée ne prend pas en charge les distances cosinus, j'ai également trouvé un package appelé arulesavec une dissimilarity()fonction mais cela ne fonctionne que sur les données binaires.


5
Il peut être plus rapide d'écrire votre propre fonction de dissimilarité cosinus.
supposé normal

2
Le cosinus est la similitude, pas la dissemblance. Vous pouvez cependant transformer le cosinus en distance euclidienne des données mises à l'échelle: d = sqrt (2 * (1-cos)).
ttnphns

Réponses:


29

Comme @Max l'a indiqué dans les commentaires (+1), il serait plus simple "d'écrire le vôtre" que de passer du temps à le chercher ailleurs. Comme nous le savons, la similitude cosinus entre deux vecteurs de longueur n estUNE,Bn

C=je=1nUNEjeBjeje=1nUNEje2je=1nBje2

qui est simple à générer R. Soit Xla matrice où les lignes sont les valeurs dont nous voulons calculer la similitude. Ensuite, nous pouvons calculer la matrice de similitude avec le Rcode suivant :

cos.sim <- function(ix) 
{
    A = X[ix[1],]
    B = X[ix[2],]
    return( sum(A*B)/sqrt(sum(A^2)*sum(B^2)) )
}   
n <- nrow(X) 
cmb <- expand.grid(i=1:n, j=1:n) 
C <- matrix(apply(cmb,1,cos.sim),n,n)

Ensuite, la matrice Cest la matrice de similitude cosinus et vous pouvez la transmettre à la fonction de carte thermique que vous aimez (la seule que je connaisse image()).


Merci, c'est utile. En fait, je ne veux pas tracer la matrice elle-même mais plutôt avoir une fonction de distance pour regrouper une autre carte thermique que j'ai.
Greg Slodkowicz

@GregSlodkowicz, OK, vous pouvez peut-être transmettre cette matrice à la fonction que vous utilisez. De plus, si vous avez trouvé cette réponse utile, veuillez envisager un vote positif (ou accepter la réponse si vous la considérez comme définitive) :)
Macro

Génial, grâce à votre réponse et au commentaire de ttnphns, j'ai pu faire ce que je voulais. Maintenant, j'aimerais avoir une métrique différente lors du clustering des lignes que lors du clustering des colonnes, mais peut-être que cela pousse ...
Greg Slodkowicz

Apparemment, je n'ai pas assez de points pour pouvoir commenter. Je voulais juste offrir une version légèrement modifiée de la belle réponse de Macro. C'est ici. # Version ChirazB de cos.sim () par Macro # où S = X% *% t (X) cos.sim.2 <- fonction (S, ix) {i <- ix [1] j <- ix [2 ] return (S [i, j] / sqrt (S [i, i] * S [j, j]))} #test X <- matrice (rnorm (20), nrow = 5, ncol = 4) S < - X% *% t (X) n <- nrow (X) idx.arr <- expand.grid (i = 1: n, j = 1: n) C <- matrice (appliquer (idx.arr, 1, cos.sim, X), n, n) C2 <- matrice (appliquer (idx.arr, 1, cos.sim.2, S), n, n) Je n'aime pas la variable globale, c'est pourquoi j'ai inclus S comme paramètre.
Chiraz BenAbdelkader


4

La fonction suivante peut être utile lorsque vous travaillez avec des matrices, au lieu de vecteurs 1-d:

# input: row matrices 'ma' and 'mb' (with compatible dimensions)
# output: cosine similarity matrix

cos.sim=function(ma, mb){
  mat=tcrossprod(ma, mb)
  t1=sqrt(apply(ma, 1, crossprod))
  t2=sqrt(apply(mb, 1, crossprod))
  mat / outer(t1,t2)
}

4

Certaines réponses ci-dessus sont inefficaces sur le plan informatique, essayez ceci;


Pour la matrice de similitude cosinus

Matrix <- as.matrix(DF)
sim <- Matrix / sqrt(rowSums(Matrix * Matrix))
sim <- sim %*% t(sim)

Convertir en matrice de dissimilarité cosinus (matrice de distance).

D_sim <- as.dist(1 - sim)

0

En augmentant une partie du code précédent (de @Macro) sur ce problème, nous pouvons envelopper dans une version plus propre dans ce qui suit:

df <- data.frame(t(data.frame(c1=rnorm(100),
                              c2=rnorm(100),
                              c3=rnorm(100),
                              c4=rnorm(100),
                              c5=rnorm(100),
                              c6=rnorm(100))))

#df[df > 0] <- 1
#df[df <= 0] <- 0



apply_cosine_similarity <- function(df){
  cos.sim <- function(df, ix) 
  {
    A = df[ix[1],]
    B = df[ix[2],]
    return( sum(A*B)/sqrt(sum(A^2)*sum(B^2)) )
  }   
  n <- nrow(df) 
  cmb <- expand.grid(i=1:n, j=1:n) 
  C <- matrix(apply(cmb,1,function(cmb){ cos.sim(df, cmb) }),n,n)
  C
}
apply_cosine_similarity(df)

J'espère que cela t'aides!

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.