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

I have a matrix called "mat" and a smaller matrix called "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 calculate the distance between each row of the mat with each row of the center. For example, the distance between the mat [1,] and the center [1,] can be calculated as

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

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

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

Repeat this process for each row of the mat, I will return

  [,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 really hoped someone would tell me how to do this with some apply () function, maybe mapply (), I think.

thanks

+6
source share
5 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 
+4
source

If you want to apply one thing for the expressiveness of the code, but it still loops, just a different syntax. This can be done without any loops or with a very small center value instead of mat . I would first transfer it first, because it’s wise to get used to getting out of the application statement as much as possible. (The answer to BrodieG is pretty much identical to the function.) They work because R automatically processes a smaller vector along the matrix and does it much faster than apply or for .

 tm <- t(mat) apply(center, 1, function(m){ colSums((tm - m)^2) }) 
+4
source

Use dist , and then extract the appropriate submatrix:

 ix <- 1:nrow(mat) as.matrix( dist( rbind(mat, center) )^2 )[ix, -ix] 6 7 # 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 

REVISION: slightly simplified.

+2
source

It will solve it

 t(apply(mat,1,function(row){ d1<-sum((row-center[1,])^2) d2<-sum((row-center[2,])^2) return(c(d1,d2)) })) 

Result:

  [,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 
+1
source

You can also use outer

 d <- function(i, j) sum((mat[i, ] - center[j, ])^2) outer(1:nrow(mat), 1:nrow(center), Vectorize(d)) 
+1
source

All Articles