Gibt es eine R-Funktion, die die Cosinus-Unähnlichkeitsmatrix berechnet? [geschlossen]


19

Ich möchte eine Heatmap mit Zeilenclustering basierend auf Kosinusabständen erstellen. Ich benutze R und heatmap.2()um die Figur zu machen. Ich kann sehen, dass es einen distParameter in gibt, heatmap.2aber ich kann keine Funktion finden, um die Cosinus-Unähnlichkeitsmatrix zu erzeugen. Die eingebaute distFunktion unterstützt keine Kosinusabstände. Ich habe auch ein Paket gefunden, das arulesmit einer dissimilarity()Funktion aufgerufen wird, aber es funktioniert nur mit Binärdaten.


5
Es kann schneller sein, eine eigene Cosinus-Unähnlichkeitsfunktion zu schreiben.
Angenommen, normal

2
Kosinus ist Ähnlichkeit, nicht Unähnlichkeit. Sie können jedoch den Cosinus in einen euklidischen Abstand skalierter Daten umwandeln: d = sqrt (2 * (1-cos)).
TTNPHNS

Dieselbe Frage zu SO: Finden Sie die
Kosinusähnlichkeit

Antworten:


28

Wie @Max in den Kommentaren (+1) angegeben hat, ist es einfacher, "eigene" zu schreiben, als Zeit damit zu verbringen, woanders danach zu suchen. Wie wir wissen, ist die Kosinus Ähnlichkeit zwischen zwei Vektoren mit der Länge istEIN,Bn

C=ich=1nEINichBichich=1nEINich2ich=1nBich2

das ist einfach zu generieren in R. Sei Xdie Matrix, in der die Zeilen die Werte sind, zwischen denen die Ähnlichkeit berechnet werden soll. Dann können wir die Ähnlichkeitsmatrix mit dem folgenden RCode berechnen :

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)

Dann ist die Matrix Cdie Cosinus-Ähnlichkeitsmatrix und Sie können sie an jede beliebige Heatmap-Funktion weitergeben (die einzige, die mir bekannt ist, ist image()).


Danke, das ist hilfreich. Eigentlich möchte ich die Matrix nicht selbst zeichnen, sondern habe eine Distanzfunktion zum Clustering einer anderen Heatmap, die ich habe.
Greg Slodkowicz

@GregSlodkowicz, OK, vielleicht können Sie diese Matrix an die von Ihnen verwendete Funktion übergeben. Wenn Sie diese Antwort hilfreich fanden, ziehen Sie bitte eine positive Bewertung in Betracht (oder akzeptieren Sie die Antwort, wenn Sie sie für endgültig halten) :)
Makro

Großartig, dank Ihrer Antwort und des Kommentars von ttnphns konnte ich tun, was ich will. Jetzt hätte ich gerne eine andere Metrik, wenn ich Zeilen gruppiere als wenn ich Spalten gruppiere, aber vielleicht drängt das ...
Greg Slodkowicz

Anscheinend habe ich nicht genug Punkte, um einen Kommentar abgeben zu können. Ich wollte nur eine leicht modifizierte Version von Macros netter Antwort anbieten. Hier ist es. # ChirazBs Version von cos.sim () nach Makro # wobei S = X% *% t (X) cos.sim.2 <- Funktion (S, ix) {i <- ix [1] j <- ix [2 ] return (S [i, j] / sqrt (S [i, i] * S [j, j])} #test X <- matrix (rnorm (20), nrow = 5, ncol = 4) S < - X% *% t (X) n <- nrow (X) idx.arr <- expand.grid (i = 1: n, j = 1: n) C <- Matrix (anwenden (idx.arr, 1, cos.sim, X), n, n) C2 <- Matrix (anwenden (idx.arr, 1, cos.sim.2, S), n, n) Ich mag keine globalen Variablen, deshalb habe ich S eingeschlossen als Parameter.
Chiraz BenAbdelkader


4

Die folgende Funktion kann beim Arbeiten mit Matrizen anstelle von 1-d-Vektoren hilfreich sein:

# 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

Einige der obigen Antworten sind rechnerisch ineffizient. Versuchen Sie dies.


Für Cosinus-Ähnlichkeitsmatrix

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

In Cosinus-Unähnlichkeitsmatrix (Distanzmatrix) konvertieren.

D_sim <- as.dist(1 - sim)

0

Wenn Sie einen Teil des vorherigen Codes (von @Macro) zu diesem Thema hochfahren, können Sie diesen im Folgenden in eine übersichtlichere Version umschließen:

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)

Hoffe das hilft!

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.