Czy istnieje funkcja R, która będzie obliczać macierz różnicy cosinus? [Zamknięte]


20

Chciałbym zrobić mapę cieplną z grupowaniem wierszy na podstawie odległości cosinusowych. Używam R i heatmap.2()do robienia figury. Widzę, że zawiera distparametr, heatmap.2ale nie mogę znaleźć funkcji do wygenerowania macierzy różnicy cosinus. Wbudowana distfunkcja nie obsługuje odległości cosinus, ja również znaleźć pakiet o nazwie arulesz dissimilarity()funkcji, ale to działa tylko na danych binarnych.


5
Szybsze może być napisanie własnej funkcji niepodobnej do cosinusa.
— zakłada się, że normalny

2
Cosinus to podobieństwo, a nie odmienność. Można jednak zamienić cosinus na euklidesową odległość skalowanych danych: d = sqrt (2 * (1-cos)).
— ttnphns

Odpowiedzi:


29

Jak wskazał @Max w komentarzach (+1), łatwiej byłoby „napisać własne” niż spędzać czas na szukaniu go gdzie indziej. Jak wiemy, podobieństwo cosinus między dwoma wektorami o długości n wynosiZA,bn

do=∑ja=1nZAjabja∑ja=1nZAja2)⋅∑ja=1nbja2)

co jest łatwe do wygenerowania w R. Niech Xbędzie macierzą, w której wiersze są wartościami, dla których chcemy obliczyć podobieństwo. Następnie możemy obliczyć macierz podobieństwa za pomocą następującego Rkodu:

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)

Następnie macierz Cjest macierzą podobieństwa cosinus i można ją przekazać do dowolnej funkcji mapy cieplnej, którą lubisz (jedyną, którą znam image()).


Dzięki, to jest pomocne. W rzeczywistości nie chcę drukować samej macierzy, ale raczej mam funkcję odległości do grupowania innej mapy cieplnej, którą mam.
— Greg Slodkowicz

@GregSlodkowicz, OK, no cóż, być może możesz przekazać tę macierz funkcji, której używasz. Ponadto, jeśli uznasz, że ta odpowiedź jest pomocna, rozważ wzięcie udziału w głosowaniu (lub zaakceptowanie odpowiedzi, jeśli uważasz ją za ostateczną) :)
— Makro

Świetnie, dzięki twojej odpowiedzi i komentarzowi ttnphns mogłem zrobić to, co chciałem. Teraz chciałbym mieć inną metrykę podczas grupowania wierszy niż podczas grupowania kolumn, ale może to popycha ...
— Greg Slodkowicz

Najwyraźniej nie mam wystarczającej liczby punktów, aby móc komentować. Chciałem tylko zaoferować nieco zmodyfikowaną wersję ładnej odpowiedzi Macro. Oto jest # Wersja ChirazB cos.sim () przez Macro # gdzie S = X% *% t (X) cos.sim.2 <- funkcja (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 <- matryca (zastosowanie (idx.arr, 1, cos.sim, X), n, n) C2 <- matryca (zastosowanie (idx.arr, 1, cos.sim.2, S), n, n) Nie lubię zmiennej globalnej, dlatego zawarłem S jako parametr.
— Chiraz BenAbdelkader


4

Następująca funkcja może być przydatna podczas pracy z macierzami zamiast wektorów 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

Niektóre powyższe odpowiedzi są nieskuteczne obliczeniowo, spróbuj tego;


Dla macierzy podobieństwa cosinus

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

Konwertuj na macierz różnicy cosinusów (macierz odległości).

D_sim <- as.dist(1 - sim)

0

Poświęcając trochę poprzedniego kodu (z @Macro) na ten temat, możemy zawinąć to w czystszą wersję w następujący sposób:

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)

Mam nadzieję że to pomoże!

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.