Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use some apply function to solve what requires two for-loops in R

Tags:

for-loop

r

apply

I have a matrix, named "mat", and a smaller matrix, named "center".

temp = c(1.8421,5.6586,6.3526,2.904,3.232,4.6076,4.8,3.2909,4.6122,4.9399)
mat = matrix(temp, ncol=2)
       [,1]   [,2]
[1,] 1.8421 4.6076
[2,] 5.6586 4.8000
[3,] 6.3526 3.2909
[4,] 2.9040 4.6122
[5,] 3.2320 4.9399

center = matrix(c(3, 6, 3, 2), ncol=2)

     [,1] [,2]
[1,]    3    3
[2,]    6    2

I need to compute the distance between each row of mat with every row of center. For example, the distance of mat[1,] and center[1,] can be computed as

diff = mat[1,]-center[1,]
t(diff)%*%diff
        [,1]
[1,] 3.92511

Similarly, I can find the distance of mat[1,] and center[2,]

diff = mat[1,]-center[2,]
t(diff)%*%diff
         [,1]
[1,] 24.08771

Repeat this process for each row of mat, I will end up with

          [,1]      [,2]
[1,]  3.925110 24.087710
[2,] 10.308154  7.956554
[3,] 11.324550  1.790750
[4,]  2.608405 16.408805
[5,]  3.817036 16.304836

I know how to implement it with for-loops. I was really hoping someone could tell me how to do it with some kind of an apply() function, maybe mapply() I guess.

Thanks

like image 681
wen Avatar asked Feb 15 '14 21:02

wen


2 Answers

apply(center, 1, function(x) colSums((x - t(mat)) ^ 2))
#           [,1]      [,2]
# [1,]  3.925110 24.087710
# [2,] 10.308154  7.956554
# [3,] 11.324550  1.790750
# [4,]  2.608405 16.408805
# [5,]  3.817036 16.304836
like image 191
BrodieG Avatar answered Sep 19 '22 00:09

BrodieG


If you want the apply for expressiveness of code that's one thing but it's still looping, just different syntax. This can be done without any loops, or with a very small one across center instead of mat. I'd just transpose first because it's wise to get into the habit of getting as much as possible out of the apply statement. (The BrodieG answer is pretty much identical in function.) These are working because R will automatically recycle the smaller vector along the matrix and do it much faster than apply or for.

tm <- t(mat)
apply(center, 1, function(m){
    colSums((tm - m)^2) })
like image 43
John Avatar answered Sep 19 '22 00:09

John