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.

Greg Słodkowicz
źródło
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
To samo pytanie dotyczące SO: Znajdź podobieństwo cosinus między dwiema tablicami
smci

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=1nZAjabjaja=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()).

Makro
źródło
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)
}
Kimsche
źródło
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)
Ćwiek
źródło
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!

bmc
źródło