Esiste una funzione R che calcolerà la matrice di dissomiglianza del coseno? [chiuso]


20

Vorrei creare una mappa di calore con raggruppamento di righe basato sulle distanze del coseno. Sto usando R e heatmap.2()per fare la figura. Vedo che è presente un distparametro heatmap.2ma non riesco a trovare una funzione per generare la matrice di dissomiglianza del coseno. La distfunzione integrata non supporta le distanze del coseno, ho anche trovato un pacchetto chiamato arulescon una dissimilarity()funzione ma funziona solo su dati binari.


5
Potrebbe essere più veloce scrivere la propria funzione di dissimilarità del coseno.
assunto normale il

2
Il coseno è somiglianza, non dissomiglianza. Tuttavia, puoi trasformare il coseno in distanza euclidea di dati in scala: d = sqrt (2 * (1-cos)).
ttnphns,

Risposte:


29

Come indicato da @Max nei commenti (+1) sarebbe più semplice "scrivere il proprio" piuttosto che passare il tempo a cercarlo altrove. Come sappiamo, la somiglianza del coseno tra due vettori UN,B di lunghezza n è

C=Σio=1nUNioBioΣio=1nUNio2Σio=1nBio2

che è semplice da generare R. Lascia che Xsia la matrice in cui le righe sono i valori che vogliamo calcolare la somiglianza tra. Quindi possiamo calcolare la matrice di somiglianza con il seguente Rcodice:

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)

Quindi la matrice Cè la matrice di somiglianza del coseno e puoi passarla a qualsiasi funzione della mappa di calore che ti piace (l'unica con cui ho familiarità è image()).


Grazie, è utile In realtà, non voglio tracciare la matrice stessa, ma piuttosto ho una funzione di distanza per il raggruppamento di un'altra mappa di calore che ho.
Greg Slodkowicz,

@GregSlodkowicz, OK, forse puoi passare questa matrice alla funzione che stai utilizzando. Inoltre, se hai trovato utile questa risposta, considera un voto (o accetta la risposta se la consideri definitiva) :)
Macro

Ottimo, grazie alla tua risposta e al commento di ttnphns sono stato in grado di fare quello che voglio. Ora vorrei avere una metrica diversa quando si raggruppano le righe rispetto a quando si raggruppano le colonne, ma forse questo lo sta spingendo ...
Greg Slodkowicz

Apparentemente non ho abbastanza punti per poter commentare. Volevo solo offrire una versione leggermente modificata della bella risposta di Macro. Ecco qui. # Versione di ChirazB di cos.sim () di Macro # dove S = X% *% t (X) cos.sim.2 <- function (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 (applica (idx.arr, 1, cos.sim, X), n, n) C2 <- matrix (apply (idx.arr, 1, cos.sim.2, S), n, n) Non mi piace la variabile globale, ecco perché ho incluso S come parametro
Chiraz BenAbdelkader l'


4

La seguente funzione potrebbe essere utile quando si lavora con le matrici, anziché i vettori 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

Alcune risposte sopra sono computazionalmente inefficienti, prova questo;


Per matrice di somiglianza del coseno

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

Converti in matrice di diversità del coseno (matrice di distanza).

D_sim <- as.dist(1 - sim)

0

Rampicando parte del codice precedente (da @Macro) su questo problema, possiamo includerlo in una versione più pulita nel seguente:

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)

Spero che sia di aiuto!

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.