Tell me more ×
Cross Validated is a question and answer site for statisticians, data analysts, data miners and data visualization experts. It's 100% free, no registration required.

I would like to make a heatmap with row clustering based on cosine distances. I'm using R and heatmap.2() for making the figure. I can see that there's a dist parameter in heatmap.2 but I cannot find a function to generate the cosine dissimilarity matrix. The builtin dist function doesn't support cosine distances, I also found a package called arules with a dissimilarity() function but it only works on binary data.

share|improve this question
2  
It may be faster to write your own cosine dissimilarity function. – Max Jul 3 '12 at 12:45
2  
Cosine is similarity, not dissimilarity. You can, however, turn cosine into euclidean distance of scaled data: d=sqrt(2*(1-cos)). – ttnphns Jul 3 '12 at 14:51

1 Answer

up vote 7 down vote accepted

As @Max indicated in the comments (+1) it would be simpler to "write your own" than to spend time looking for it somewhere else. As we know, the cosine similarity between two vectors $A,B$ of length $n$ is

$$ C = \frac{ \sum \limits_{i=1}^{n}A_{i} B_{i} }{ \sqrt{\sum \limits_{i=1}^{n} A_{i}^2} \cdot \sqrt{\sum \limits_{i=1}^{n} B_{i}^2} } $$

which is straightforward to generate in R. Let X be the matrix where the rows are the values we want to compute the similarity between. Then we can compute the similarity matrix with the following R code:

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)

Then the matrix C is the cosine similarity matrix and you can pass it to whatever heatmap function you like (the only one I'm familiar with is image()).

share|improve this answer
Thanks, this is helpful. Actually, I don't want to plot the matrix itself but rather have a distance function for clustering of another heatmap that I have. – Greg Slodkowicz Jul 5 '12 at 12:01
@GregSlodkowicz, OK well perhaps you can pass this matrix to the function you're using. Also, if you've found this answer helpful please consider an upvote (or accepting the answer if you consider it definitive) :) – Macro Jul 5 '12 at 12:26
Great, thanks to your reply and ttnphns's comment I was able to do what I want. Now I would like to have a different metric when clustering rows than when clustering columns but maybe that's pushing it... – Greg Slodkowicz Jul 7 '12 at 10:20

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.